From c6957ef715f38cd0b993275cbff7b47ea31efead Mon Sep 17 00:00:00 2001 From: ocogeclub Date: Fri, 1 Oct 2021 20:39:50 +0900 Subject: [PATCH] =?UTF-8?q?[update]=20Electron15=20=E3=81=AE=E3=83=87?= =?UTF-8?q?=E3=83=95=E3=82=A9=E3=83=AB=E3=83=88=E3=81=AB=E5=BE=93=E3=81=84?= =?UTF-8?q?=E3=80=81nodeIntegration:=20false,=20contextIsolation:=20true?= =?UTF-8?q?=20=E3=81=A7=E5=8B=95=E4=BD=9C=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=82=B3=E3=83=BC=E3=83=89=E3=82=92=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E3=80=81remote=20=E3=82=92=E3=82=84=E3=82=81=E3=81=A6=20ipc=20?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=99=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 17 +- index.js | 732 +++++- index_elutil.js | 315 +++ ...ndmark_68_tiny_model-weights_manifest.json | 39 + lib/models/face_landmark_68_tiny_model.bin | Bin 0 -> 77224 bytes ..._face_detector_model-weights_manifest.json | 31 +- ...el-shard1 => tiny_face_detector_model.bin} | Bin local_modules/@ocogeclub/bme280/BME280.js | 493 ++-- main.js | 178 ++ package-lock.json | 2252 ----------------- package.json | 13 +- preload.js | 19 + ugj_blocks.js | 118 +- ugj_const.js | 7 - ugj_eleclib.js | 240 -- ugj_script.js | 3 + yarn.lock | 2058 +++++++++++++++ 17 files changed, 3589 insertions(+), 2926 deletions(-) create mode 100644 index_elutil.js create mode 100644 lib/models/face_landmark_68_tiny_model-weights_manifest.json create mode 100644 lib/models/face_landmark_68_tiny_model.bin rename lib/models/{tiny_face_detector_model-shard1 => tiny_face_detector_model.bin} (100%) create mode 100644 main.js delete mode 100644 package-lock.json create mode 100644 preload.js delete mode 100644 ugj_const.js delete mode 100644 ugj_eleclib.js create mode 100644 yarn.lock diff --git a/index.html b/index.html index aec61e9..5cba945 100644 --- a/index.html +++ b/index.html @@ -597,6 +597,19 @@ once TRUE + + + FALSE + + + + + + + + 高さ + + @@ -966,9 +979,9 @@ - - + + diff --git a/index.js b/index.js index 74d2972..2b7bd06 100644 --- a/index.js +++ b/index.js @@ -1,147 +1,619 @@ -const { app, BrowserWindow, Menu, session } = require('electron'); -require('@electron/remote/main').initialize(); +'use strict'; -/** Force disable security warning */ -process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'; +let elutil = elUtil_new(); -// Keep a global reference of the window object, if you don't, the window will -// be closed automatically when the JavaScript object is garbage collected. -let win +const testfunc = () => { + elutil.openURL('http://ocoge.club'); +} -function createWindow() { - // Create the browser window. - win = new BrowserWindow({ - /** Icon */ - icon: "./icon.png", - width: 1280, - height: 940, - webPreferences: { - nodeIntegration: true, - contextIsolation: false, - enableRemoteModule: true +//============ User Customize Start =============== +// カスタムブロックカラー定義 +Blockly.HSV_SATURATION = 0.55; +Blockly.HSV_VALUE = 0.75; +var gpio_color = '0'; +var multimedia_color = '240'; +var network_color = '340'; +var special_color = '20'; +var snippets_color = '90'; +// テーマ +var theme = Blockly.Theme.defineTheme('ocoge', { + 'base': Blockly.Themes.Classic, + 'startHats': true, + 'componentStyles': { + 'toolboxBackgroundColour': 'aliceblue', + 'flyoutBackgroundColour': 'lavender', + 'toolboxForegroundColour': 'white', + 'flyoutForegroundColour': 'steelblue' + }, + 'blockStyles': { + 'gpio_blocks': { + "colourPrimary": gpio_color + }, + 'multimedia_blocks': { + "colourPrimary": multimedia_color + }, + 'network_blocks': { + "colourPrimary": network_color + }, + 'special_blocks': { + "colourPrimary": special_color + }, + 'snippets_blocks': { + "colourPrimary": snippets_color } - }) - /** Maximize Window when launch */ - win.maximize(); + }, + 'categoryStyles': { + "gpio_category": { + "colour": gpio_color + }, + "multimedia_category": { + "colour": multimedia_color + }, + "network_category": { + "colour": network_color + }, + "special_category": { + "colour": special_color + }, + "snippets_category": { + "colour": snippets_color + } + }, +}); - // and load the index.html of the app. - win.loadFile('index.html') +// Customize messages +Blockly.Msg["CONTROLS_IF_MSG_THEN"] = "ならば"; +Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"] = ""; +Blockly.Msg["MATH_CHANGE_TITLE"] = "変数 %1 を %2 増やす"; +Blockly.Msg["VARIABLES_SET"] = "変数 %1 を %2 にする"; +// Blockly.Msg["TEXT_PRINT_TITLE"] = "ダイアログに %1 を表示"; +Blockly.Msg["LOGIC_BOOLEAN_FALSE"] = "偽"; +Blockly.Msg["LOGIC_BOOLEAN_TOOLTIP"] = "真 または 偽 を返します。"; +Blockly.Msg["LOGIC_BOOLEAN_TRUE"] = "真"; +// ローカライズ対応の準備 +Blockly.Msg["UGJ_CONTROL_FOR_TITLE"] = "%1 %2 を %3 から %4 まで %5 ずつ %6 %7 %8"; +Blockly.Msg["UGJ_CONTROL_FOR_INDEX"] = "番号"; +Blockly.Msg["UGJ_CONTROL_FOR_INCREASE"] = "増やして"; +Blockly.Msg["UGJ_CONTROL_FOR_DECREASE"] = "減らして"; +Blockly.Msg["UGJ_CONTROL_FOR_TOOLTIP"] = "インデックス番号を決められた数ずつ増やし(減らし)ながら、ステートメントを実行します。"; +Blockly.Msg["UGJ_FOREACH_TITLE"] = "リスト %1 の各 %2 について %3 %4"; +Blockly.Msg["UGJ_FOREACH_ITEM"] = "項目"; +Blockly.Msg["UGJ_FOREACH_TOOLTIP"] = "リストの各項目について、その項目を変数「項目」としてステートメントを実行します。"; - // Open the DevTools. - // win.webContents.openDevTools() +Blockly.Msg["GPIOCHIP_OPEN_TITLE"] = "GPIO を使えるようにする"; +Blockly.Msg["GPIOCHIP_OPEN_TOOLTIP"] = "GPIOを初期化して接続します。"; +Blockly.Msg["GPIOCHIP_CLOSE_TITLE"] = "GPIO の後片付けをする"; +Blockly.Msg["GPIOCHIP_CLOSE_TOOLTIP"] = "GPIOとの接続を終了します。"; +Blockly.Msg["GPIOCHIP_CLOSE_TITLE"] = "GPIO の後片付けをする"; +Blockly.Msg["GPIO_CLAIM_INPUT_TITLE"] = "GPIO %1 を入力モードにして %2"; +Blockly.Msg["GPIO_CLAIM_INPUT_TOOLTIP"] = "GPIO端子を入力モードにして、プルアップ・プルダウン・無しを設定します。"; +Blockly.Msg["GPIO_CLAIM_OUTPUT_TITLE"] = "GPIO %1 を出力モードにする"; +Blockly.Msg["GPIO_CLAIM_OUTPUT_TOOLTIP"] = "GPIO端子のモードを出力に設定します。"; +Blockly.Msg["GPIO_READ_TITLE"] = "GPIO %1 の値"; +Blockly.Msg["GPIO_READ_TOOLTIP"] = "GPIO端子の値をデジタル値(0または1)で読み取ります。"; +Blockly.Msg["GPIO_WRITE_TITLE"] = "GPIO %1 の値を %2 にする"; +Blockly.Msg["GPIO_WRITE_TOOLTIP"] = "GPIO端子の値をデジタル値(0または1)で出力します。"; +Blockly.Msg["TX_SERVO_TITLE"] = "GPIO %1 のサーボモータの回転を %2 にする"; +Blockly.Msg["TX_SERVO_TOOLTIP"] = "サーボモータの回転をパルス幅(1000~2000μsec)までの数値で指定します。"; +Blockly.Msg["TX_PWM_TITLE"] = "PWM : GPIO %1 に、パルス周波数 %2 Hz, デューティー比 %3 %%で出力"; +Blockly.Msg["TX_PWM_TOOLTIP"] = "パルス周波数をセットして、GPIO端子がPWM出力できるようにします。レンジは100固定です。"; +Blockly.Msg["I2C_OPEN_TITLE"] = "アドレス %1 の I2C デバイスを開く"; +Blockly.Msg["I2C_OPEN_TOOLTIP"] = "I2C接続されたデバイスとの通信を開始します。一度にオープンできるI2Cデバイスはひとつだけです。"; +Blockly.Msg["SERIAL_OPEN_TITLE"] = "シリアルポート %1 を速度 %2 bpsで開く"; +Blockly.Msg["SERIAL_OPEN_TOOLTIP"] = "シリアルデバイスとの接続を開きます。"; +Blockly.Msg["SERIAL_CLOSE_TITLE"] = "シリアルポートを閉じる"; +Blockly.Msg["SERIAL_CLOSE_TOOLTIP"] = "シリアルデバイスとの接続を閉じます。"; +Blockly.Msg["SERIAL_WRITE_TITLE"] = "シリアルポートに %1 を送信する"; +Blockly.Msg["SERIAL_WRITE_TOOLTIP"] = "シリアル接続されたデバイスにデータを送信します。シリアルポートは開かれていなくてはいけません。"; +Blockly.Msg["SERIAL_READ_TITLE"] = "シリアルポートから %1 文字読み込む"; +Blockly.Msg["SERIAL_READ_TOOLTIP"] = "オープン済みシリアルポートから、指定のバイト数だけデータを読み込みます。"; +Blockly.Msg["I2C_CLOSE_TITLE"] = "I2C デバイスを閉じる"; +Blockly.Msg["I2C_CLOSE_TOOLTIP"] = "I2C接続されたデバイスと通信を切断します。"; +Blockly.Msg["I2C_WRITE_BYTE_TITLE"] = "デバイスに1バイトデータ %1 を送信"; +Blockly.Msg["I2C_WRITE_BYTE_TOOLTIP"] = "i2cデバイスに1バイトデータを送信します。0-0xFFの範囲の数字で入力してください。"; +Blockly.Msg["I2C_READ_BYTE_TITLE"] = "I2C デバイスから 1 バイト受け取る"; +Blockly.Msg["I2C_READ_BYTE_TOOLTIP"] = "オープン済み I2C デバイスからデータを 1 バイト受け取ります。"; +Blockly.Msg["I2C_WRITE_BYTE_DATA_TITLE"] = "レジスタ %1 に %2 を書き込む"; +Blockly.Msg["I2C_WRITE_BYTE_DATA_TOOLTIP"] = "デバイスの指定されたレジスタに1バイトを書き込みます。"; +Blockly.Msg["I2C_READ_BYTE_DATA_TITLE"] = "レジスタ %1 の値"; +Blockly.Msg["I2C_READ_BYTE_DATA_TOOLTIP"] = "デバイスの指定されたレジスタから1バイトを読み込みます。"; +Blockly.Msg["I2C_READ_DEVICE_TITLE"] = "i2cデバイスから %1 バイト受け取る"; +Blockly.Msg["I2C_READ_DEVICE_TOOLTIP"] = "デバイスから指定したバイト数のデータを受け取ります。データが指定の長さより短いこともあります。"; +Blockly.Msg["I2C_WRITE_DEVICE_TITLE"] = "i2c デバイスに %1 を送信"; +Blockly.Msg["I2C_WRITE_DEVICE_TOOLTIP"] = "i2c デバイスにデータを送信します。"; - // Emitted when the window is closed. - win.on('closed', () => { - // Dereference the window object, usually you would store windows - // in an array if your app supports multi windows, this is the time - // when you should delete the corresponding element. - win = null - }) +Blockly.Msg["UGJ_BME280_TITLE"] = "BME280(アドレス %1 )の計測値: %2 %3 %4"; +Blockly.Msg["UGJ_BME280_TOOLTIP"] = "環境センサーBME280で、気温(摂氏)、湿度(%)、気圧(hPa)を計測し、それぞれを変数に代入します。"; +Blockly.Msg["UGJ_BME280_READ_TEMP"] = "気温"; +Blockly.Msg["UGJ_BME280_READ_HUM"] = "湿度"; +Blockly.Msg["UGJ_BME280_READ_PRES"] = "気圧"; - /** For SkyWay */ - session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => { - details.requestHeaders['Origin'] = 'electron://localhost'; - callback({ - cancel: false, - requestHeaders: details.requestHeaders - }); +Blockly.Msg["UGJ_CODECHAR_TITLE"] = "コード %1 の文字"; +Blockly.Msg["UGJ_CODECHAR_TOOLTIP"] = "文字コードを文字に変換します。"; +Blockly.Msg["UGJ_CHARCODE_TITLE"] = "%1 の文字コード"; +Blockly.Msg["UGJ_CHARCODE_TOOLTIP"] = "入力テキストの1文字目の文字コードを返します。"; +Blockly.Msg["UGJ_HEXTODEC_TITLE"] = "0x %1"; +Blockly.Msg["UGJ_HEXTODEC_TOOLTIP"] = "16進数を10進数に変換します。"; +Blockly.Msg["UGJ_DECTOHEX_TITLE"] = "%1 を16進数に変換"; +Blockly.Msg["UGJ_DECTOHEX_TOOLTIP"] = "10進数を16進数に変換します。"; + +Blockly.Msg["UGJ_CANVAS_INIT_TITLE"] = "キャンバスを表示"; +Blockly.Msg["UGJ_CANVAS_INIT_TOOLTIP"] = "キャンバスを表示し、使用できるようにします。"; +Blockly.Msg["UGJ_FACEAPI_TITLE"] = "TensorFlowによる顔検出: %1 ランドマークを検出 %2 %3"; +Blockly.Msg["UGJ_FACEAPI_TOOLTIP"] = "TensorFlow とFaceAPI をロードし、顔検出をできるようにします。"; + +Blockly.Msg["UGJ_SLEEP_TITLE"] = "%1 秒待つ"; +Blockly.Msg["UGJ_SLEEP_TOOLTIP"] = "指定した秒数だけ処理を中断します。"; + +// Customize Toolbox +class CustomCategory extends Blockly.ToolboxCategory { + /** Constructor for a custom category. @override */ + constructor(categoryDef, toolbox, opt_parent) { + super(categoryDef, toolbox, opt_parent); + } + /** @override */ + addColourBorder_(colour) { + this.rowDiv_.style.backgroundColor = colour; + } + /** @override */ + setSelected(isSelected) { + // We do not store the label span on the category, so use getElementsByClassName. + var labelDom = this.rowDiv_.getElementsByClassName('blocklyTreeLabel')[0]; + if (isSelected) { + // Change the background color of the div to white. + this.rowDiv_.style.backgroundColor = 'white'; + // Set the colour of the text to the colour of the category. + labelDom.style.color = this.colour_; + this.iconDom_.style.color = this.colour_; + } else { + // Set the background back to the original colour. + this.rowDiv_.style.backgroundColor = this.colour_; + // Set the text back to white. + labelDom.style.color = 'white'; + this.iconDom_.style.color = 'white'; + } + // This is used for accessibility purposes. + Blockly.utils.aria.setState(/** @type {!Element} */(this.htmlDiv_), + Blockly.utils.aria.State.SELECTED, isSelected); + } +} +Blockly.registry.register( + Blockly.registry.Type.TOOLBOX_ITEM, + Blockly.ToolboxCategory.registrationName, + CustomCategory, true); +//============ User Customize End =============== + + +//背景canvasとマスコットの準備 +const ugj_canvasBgImg = (imgSrc, x, y) => { //x,y == -1: center or middle + let el = document.getElementById('canvas_bg'); + let ctx = el.getContext('2d'); + ctx.fillStyle = 'rgb(255,255,255)'; + ctx.fillRect(0, 0, 480, 360); + let img = new Image(); + img.src = imgSrc; + img.onload = () => { + if (x < 0) { //センタリング + let w = img.width; + if (w >= 480) x = 0; + else x = Math.floor((480 - w) / 2); + } + if (y < 0) { //縦中寄せ + let h = img.height; + if (h >= 360) y = 0; + else y = Math.floor((360 - h) / 2); + } + ctx.drawImage(img, x, y); + } +}; + +// HTML部品のインスタンス - 画面上の必要な部品はすべてここで取得しておく +let ugjel_displayArea = document.getElementById('display_area'); // ディスプレイ部 +let ugjel_blackboard = document.getElementById('blackboard'); // 黒板 +let ugjel_inputForm = document.getElementById('inputForm'); // 入力フォーム +let ugjel_inputBox = document.getElementById('inputBox'); // 入力フィールド + +// その他のプロパティ +let ugj_inputEvLstnrID = 0; // 入力フォームの動的イベントリスナの最新のID +let ugj_sounds = (names => { // サウンドファイルのいろいろの配列の初期化 + let sounds = []; + names.forEach(value => { + let filepath = `./sounds/${value}.wav`; + sounds[value] = { 'file': filepath, 'audio': new Audio(filepath) }; + }); + return sounds; +})(['meow', 'bounce', 'type_chime', 'type_dink', 'type_tap', 'type_space', 'type_return']); // サウンドファイルのベース名のリスト + +// メソッド + +// マスコット選択 +const ugj_selectMascot = async () => { + let fname = await elutil.selectMascotFile(); + if (fname) { + ugj_canvasBgImg(fname, -1, -1); + elutil.setMascotFilePath(fname); + } +} + +// サウンド再生 - 連続再生のため、再生開始後すぐにオーディオ要素を再生成する +const ugj_soundPlay = soundName => { + ugj_sounds[soundName]['audio'].play(); + ugj_sounds[soundName]['audio'] = new Audio(ugj_sounds[soundName]['file']); +}; + +// OK,Cancel 2択のダイアログを表示 +const ugj_confirm = (title, message, callback) => { + CustomDialog.show(title, message, { + showOkay: true, + onOkay: () => callback(true), + showCancel: true, + onCancel: () => callback(false) + }); +}; + +const ugj_htmlEntities = str =>// HTMLエンティティのエスケープ + String(str).replace(//g, '>').replace(/"/g, '"');//.replace(/&/g, '&').replace(/ /g, ' '); + +// 新規ワークスペース +const ugj_newWorkspace = () => { + ugj_confirm('新規ワークスペース', '保存していない内容はすべて破棄されます。よろしいですか?', okey => { + if (okey) { + workspace.clear(); + elutil.newFile(); + } }); } -// This method will be called when Electron has finished -// initialization and is ready to create browser windows. -// Some APIs can only be used after this event occurs. -// app.on('ready', createWindow) -app.on('ready', () => { - createWindow(); - /** Custom Menu */ - let template = [ - { - label: 'Menu', - submenu: [ - { - label: 'Toggle Menu Bar', - click: () => { - win.setMenuBarVisibility(!win.menuBarVisible); - }, - accelerator: "CommandOrControl+Shift+M" - }, - { - label: 'Reload', - click: () => { - win.reload(); - }, - accelerator: "F5" - }, - { - label: 'Mascot', - click: (item, focusedWindow) => { - if (focusedWindow) - focusedWindow.webContents.executeJavaScript('ugj_selectMascot()'); - }, - accelerator: "CommandOrControl+M" - }, - { - label: 'Toggle Developer Tools', - click: () => { - win.webContents.toggleDevTools() - }, - accelerator: "F12" - }, - { - label: 'About', - click: () => { - var os = require('os'); - var detail = 'Version: ' + process.env.npm_package_version + '\n' - + 'Node.js: ' + process.versions.node + '\n' - + 'Chrome: ' + process.versions.chrome + '\n' - + 'Electron: ' + process.versions.electron + '\n' - + 'V8: ' + process.versions.v8 + '\n' - + 'OS: ' + os.type + ' ' + os.arch + ' ' + os.version + ' ' + os.release; - var options = { - type: 'info', - buttons: ['OK'], - title: 'OCoGe', - message: 'OCoGe - Oiwa Code Generator', - detail: detail - }; - require('electron').dialog.showMessageBox(win, options); - }, - accelerator: "CommandOrControl+I" - }, - { - label: 'Quit', - click: () => { - app.quit(); - }, - accelerator: "CommandOrControl+Q" - } - ] +// ワークスペースをファイルに保存・読込 +const ugj_saveWorkspaceToFile = async () => { + let xml = Blockly.Xml.workspaceToDom(workspace); + let xml_text = Blockly.Xml.domToText(xml); + if (await elutil.saveWsFile(xml_text) === false) { + alert('保存できませんでした。'); + } +} +const ugj_loadWorkspaceFromFile = async () => { + let xml_text = await elutil.loadWsFile(); + if (xml_text.length > 0) { + let xml = Blockly.Xml.textToDom(xml_text); + Blockly.Xml.domToWorkspace(xml, workspace); + } +} + +// ワークスペースを別名で保存 +const ugj_saveWorkspaceAs = () => { + elutil.newFile(); + ugj_saveWorkspaceToFile(); +} + +// ワークスペースをローカルストレージに保存・読込 +const ugj_saveWorkspace = () => { + // Workspace + let xml = Blockly.Xml.workspaceToDom(workspace); + let xml_text = Blockly.Xml.domToText(xml); + localStorage.setItem("ocoge.xml", xml_text); +} +const ugj_loadWorkspace = () => { + // Workspace + let xml_text = localStorage.getItem("ocoge.xml"); + if (xml_text !== null) { + if (xml_text.length != 0) { + let xml = Blockly.Xml.textToDom(xml_text); + Blockly.Xml.domToWorkspace(xml, workspace); } - ] - const menu = Menu.buildFromTemplate(template); - Menu.setApplicationMenu(menu); - win.setMenuBarVisibility(false); -}) - - -// Quit when all windows are closed. -app.on('window-all-closed', () => { - // On macOS it is common for applications and their menu bar - // to stay active until the user quits explicitly with Cmd + Q - if (process.platform !== 'darwin') { - app.quit() } -}) +} -app.on('activate', () => { - // On macOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (win === null) { - createWindow() +// // Python コードフォーマッタ YAPF をコール +// const ugj_pyBeautify = (code) => { +// let formatted; +// formatted = window.ocogeapi.child_process.spawnSync('python3', ['-m', 'yapf'], { input: code }).stdout.toString(); +// return formatted; +// } +// Python コードフォーマッタ Black をコール +const ugj_pyBeautify = (code) => { + let formatted; + formatted = window.ocogeapi.child_process.spawnSync('python3', ['-m', 'black', '-'], { input: code }).stdout.toString(); + return formatted; +} + +// ワークスペースからコードを生成して必要であれば整形処理をする +const ugj_createCode = (args) => { + const addAsync = args.async || false; + const beautify = args.beautify || false; + const prettify = args.prettify || false; + const ext = args.ext || 'js'; + + let code; + if (ext == 'py') { // Python コード出力 + try { + code = Blockly.Python.workspaceToCode(workspace); + } catch (e) { // Pythonコードを持たないブロックがある場合 + window.alert('Python 非対応のブロックが使用されています。\n' + e.message); + } + code = Blockly.Python.workspaceToCode(workspace); + } + else { // Javascript コード出力 + code = Blockly.JavaScript.workspaceToCode(workspace); } -}) -// In this file you can include the rest of your app's specific main process -// code. You can also put them in separate files and require them here. + if (ext == 'py') { //Python + // コードを綺麗に + if (beautify) code = ugj_pyBeautify(code); + } else { // JavaScript + // await使用のため、必要に応じてコード全体をasync付き即時関数でラップ + if (addAsync) { + code = [ + '(async () => {', + code, + '})();' + ].join('\n'); + } + // コードを綺麗に + if (beautify) code = js_beautify(code, { indent_size: 2 }); + } + // シンタックスハイライト(HTML化): 先に HTML エンティティをエスケープ + if (prettify) code = PR.prettyPrintOne(ugj_htmlEntities(code), ext, true); + + return code; +} + +// ブロックスクリプト実行 +const ugj_runCode = async () => { + document.activeElement.blur(); //実行ボタンからフォーカスを外す:エンターキー押下が悪さをするため + let code = ugj_createCode({ 'async': true }); + await eval(code).catch(e => { alert(e); }); +} + +// コードをダイアログで表示・保存 +// エレメントのオブジェクトとかコールバックとか Python対応とか +// 色々この中で完結させてみる +const ugj_showCode = () => { + var ext = 'js'; + const dialog = document.getElementById('codeDlg'); + const content = document.getElementById('dlgContent'); + const btn_close = document.getElementById('dlgClose'); + const btn_export = document.getElementById('dlgExport'); + const chkbox_cli = document.getElementById('dlgCli'); + + const dialog_title = document.getElementById('dlgTitle'); + + const showCode = () => + content.innerHTML = ugj_createCode({ 'beautify': true, 'ext': ext, 'prettify': true }); + + showCode(); + + dialog.showModal(); + + const close_cb = () => { + dialog.close(); + btn_close.removeEventListener('click', close_cb); + btn_export.removeEventListener('click', export_cb); + } + const export_cb = () => { + code = ugj_createCode({ 'ext': ext, 'async': true, 'beautify': true }); + // blackboardWrite()とwindow.alert()、fukidashi()をconsole.log()に書き換え、 + // document... と ugj_... と elutil... をコメントアウト(ブラウザ関連部分の追放という意味では不完全なので注意) + // あと正規表現もいい加減 + if (chkbox_cli.checked && ext == 'js') + code = code.replace(/const appendDiv[^#]*\/\/#/gm, 'const blackboardWrite = text => console.log(text);').replace('window.alert', 'console.log').replace(/ugj_fukidashi(.*), \d+(\);)/gm, 'console.log$1$2').replace(/(^(?=.*document.)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*ugj_)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*elutil.)[^;]*;)/gm, '/* $1 */'); + if (elutil.saveFile(code, ext) === false) { + alert('保存できませんでした。'); + } + close_cb(); + } + btn_close.addEventListener('click', close_cb); + btn_export.addEventListener('click', export_cb); + document.addEventListener('keypress', (ev) => { + if (ev.key == 'p' && ext == 'js') { + ext = 'py'; + showCode(); + } + }); + document.addEventListener('keyup', (ev) => { + if (ev.key == 'p') { + ext = 'js'; + showCode(); + } + }); +} + + +// フキダシ +let ugj_fdTimeoutID = null; +let ugj_fdRecentBox = null; +const ugj_fukidashi = (text, sec) => { + // Canvas Context + const context = document.getElementById('canvas').getContext('2d'); + // 吹き出しを消去する関数 + const clearFd = (x, y, w, h) => context.clearRect(x, y, w, h); + // 前回の思い出を忘れる + if (ugj_fdRecentBox !== null) { + clearFd(ugj_fdRecentBox.x, ugj_fdRecentBox.y, ugj_fdRecentBox.w, ugj_fdRecentBox.h); + clearTimeout(ugj_fdTimeoutID); + ugj_fdRecentBox = null; + } + + // 基本設定 + let rtopX = 170; // フキダシ右上 X座標 + let rtopY = 40; // フキダシ右上 Y座標 + let boxWidth = 140; + let padding = 5; + let radius = 5;// 円弧の半径 + + // 吹き出しの背景色 + context.fillStyle = "#b7e6ff"; + + // テキスト設定 + let limitedWidth = boxWidth - (padding * 2); + let size = 14; + context.font = size + "px ''"; + + // テキスト調整 行に分解 + let lineTextList = text.split("\n"); + let newLineTextList = []; + lineTextList.forEach((lineText) => { + if (context.measureText(lineText).width > limitedWidth) { + characterList = lineText.split("");// 1文字ずつ分割 + let preLineText = ""; + lineText = ""; + characterList.forEach((character) => { + lineText += character; + if (context.measureText(lineText).width > limitedWidth) { + newLineTextList.push(preLineText); + lineText = character; + } + preLineText = lineText; + }); + } + newLineTextList.push(lineText); + }); + let lineLength = newLineTextList.length; + + // 角丸 + let width = boxWidth;// 枠の幅 + let height = (size * lineLength) + (padding * 3); // 枠の高さ + let toRadianCoefficient = Math.PI / 180; // 角度からラジアンへの変換係数 + // 角丸原点(左上座標) + let boxOrigin = { + "x": rtopX - width, + "y": rtopY, + } + // 円弧から円弧までの直線は自動で引かれます、角度は回り方によって変わります。 + // arc(中心x, 中心y, 半径, 開始角度, 終了角度, 反時計回り) + context.beginPath(); + context.arc(boxOrigin.x + radius, boxOrigin.y + radius, radius, 180 * toRadianCoefficient, 270 * toRadianCoefficient, false);// 左上 + context.arc(boxOrigin.x + width - radius, boxOrigin.y + radius, radius, 270 * toRadianCoefficient, 0, false);// 右上 + context.arc(boxOrigin.x + width - radius, boxOrigin.y + height - radius, radius, 0, 90 * toRadianCoefficient, false);// 右下 + context.arc(boxOrigin.x + radius, boxOrigin.y + height - radius, radius, 90 * toRadianCoefficient, 180 * toRadianCoefficient, false);// 左下 + context.closePath(); + context.fill(); + + // 矢印(ヒゲ) + let arrow = { + "x": rtopX - width / 2 + 40, + "y": rtopY + height + 10, + "width": 10, + "height": 10, + } + context.beginPath(); + context.moveTo(arrow.x, arrow.y); + context.lineTo(arrow.x, arrow.y - arrow.height); + context.lineTo(arrow.x - arrow.width, arrow.y - arrow.height); + context.fill(); + + // テキスト描画 + context.fillStyle = "#000000"; + newLineTextList.forEach((lineText, index) => { + context.fillText(lineText, boxOrigin.x + padding, boxOrigin.y + padding + (size * (index + 1))); + }); + + // 描画した吹き出しの位置情報を保存 + ugj_fdRecentBox = { x: boxOrigin.x, y: boxOrigin.y, w: width, h: height + arrow.height }; + // 指定時間後に消去(0以下で自動消去なし) + if (sec > 0) { + ugj_fdTimeoutID = setTimeout(() => { + clearFd(boxOrigin.x, boxOrigin.y, width, height + arrow.height); + }, sec * 1000); + } + + // return [boxOrigin.x, boxOrigin.y, width, height+arrow.height]; + // https://qiita.com/horikeso/items/95595f379a8dfa63c34a +} + +// コードジェネレータモード(Javascript/Python切り替え) +var isPyMode; +const ugj_pyMode = (checked) => isPyMode = checked; + + +//===================================== +//======= Blockly GUI codes =========== +// Use in a block or block definition: + +// Resizable workspace injection script +var blocklyArea = document.getElementById('blocklyArea'); +var blocklyDiv = document.getElementById('blocklyDiv'); +// var workspace = Blockly.inject(blocklyDiv, +// {toolbox: document.getElementById('toolbox')}); +var workspace = Blockly.inject(blocklyDiv, + { + toolbox: document.getElementById('toolbox'), + theme: theme, + renderer: 'thrasos', + + scrollbars: true, + grid: { + spacing: 20, + length: 1, + colour: '#888',//888 + snap: true + }, + zoom: { startScale: 1.0, controls: true }, + trashcan: true, + media: './google-blockly/media/' + }); +var onresize = function (e) { + // Compute the absolute coordinates and dimensions of blocklyArea. + var element = blocklyArea; + var x = 0; + var y = 0; + do { + x += element.offsetLeft; + y += element.offsetTop; + element = element.offsetParent; + } while (element); + // Position blocklyDiv over blocklyArea. + blocklyDiv.style.left = x + 'px'; + blocklyDiv.style.top = y + 'px'; + blocklyDiv.style.width = blocklyArea.offsetWidth + 'px'; + blocklyDiv.style.height = blocklyArea.offsetHeight + 'px'; + Blockly.svgResize(workspace); +}; +window.addEventListener('resize', onresize, false); +onresize(); +Blockly.svgResize(workspace); +//===================================== +//===================================== + + +// ワークスペースの未保存の変更のフラグ +const ugj_wsUpdateCB = event => { + if (event.type != Blockly.Events.UI) { + elutil.setWsChanged(true); + } +} + +// ウィンドウロード・アンロード時 +window.onload = () => { + var menu = document.getElementById('conmenu'); //独自コンテキストメニュー + var area = document.getElementById('dlgContent'); //対象エリア + var body = document.body; //bodyエリア + body.oncontextmenu = () => false; + //右クリック時に独自コンテキストメニューを表示する + area.addEventListener('contextmenu', function (e) { + menu.style.left = e.pageX + 'px'; + menu.style.top = e.pageY + 'px'; + menu.classList.add('on'); + }); + //左クリック時に独自コンテキストメニューを非表示にする + body.addEventListener('click', function () { + if (menu.classList.contains('on')) { + menu.classList.remove('on'); + } + }); + + // ワークスペースといくつかの環境のオートリストア + ugj_loadWorkspace(); + elutil.loadPrefsFromLS(); + setTimeout(() => { // 環境設定のロードが終わってからイベントリスナを作成 + workspace.addChangeListener(ugj_wsUpdateCB); + }, 100); + // 背景canvas + ugj_canvasBgImg(elutil.getMascotFilePath(), -1, -1); +} +window.onbeforeunload = () => { + ugj_saveWorkspace(); + elutil.savePrefsToLS(); + elutil.killAllChildren(); +} diff --git a/index_elutil.js b/index_elutil.js new file mode 100644 index 0000000..a84c277 --- /dev/null +++ b/index_elutil.js @@ -0,0 +1,315 @@ +/** Electron / Node.js に由来する機能に関する諸々 */ +/** ブラウザ動作時にもちょびっと対応 */ +'use strict' + +// ファイル定数 +const ugj_const = { + doc_root: '/home/pi/Documents/ocoge_docs/', + app_name: 'ocoge', + mascot_path: './img/', + mascot_defname: 'tamachee.png', + library_path: './lib/', + executable_path: './bin/', + localStorage_fname: 'ocoge.json', + error_ja_all: 'エラーが発生しました。\n『おこげ倶楽部』までお問い合わせください。' +} + +/** クラス elUtil ****************************************************************** */ +// Electron 動作用 +class elUtil { + constructor() { + this.path = window.ocogeapi.path + this.fs = window.ocogeapi.fs + this.ipcRenderer = window.ocogeapi.electron_ipcRenderer + this.shell = window.ocogeapi.electron_shell + this.saveFilepath = null; + this.wsChanged = false; + this.mascotFilePath = this.path.join(ugj_const.mascot_path, ugj_const.mascot_defname); + this.children = []; + } + // 0で数値の桁合わせ : NUM=値 LEN=桁数 + zeroPadding(NUM, LEN) { + return (Array(LEN).join('0') + NUM).slice(-LEN); + } + // 現在の日付時刻から workspace フォルダ内のユニークなファイルパスを作成 + getUniqueFilepath() { + let today = new Date(); + let filename = today.getFullYear() + '-' + this.zeroPadding((today.getMonth() + 1), 2) + '-' + this.zeroPadding(today.getDate(), 2) + '-' + this.zeroPadding(today.getHours(), 2) + '-' + this.zeroPadding(today.getMinutes(), 2) + '-' + this.zeroPadding(today.getSeconds(), 2); + let filepath = this.path.join(ugj_const.doc_root, filename); + return filepath; + } + // リンクを外部ブラウザで開く + openURL(url) { + this.shell.openExternal(url); + } + // saveFilepath を更新 + // ウィンドウタイトルバーテキストを変更 + setSaveFilepath(filepath) { + this.saveFilepath = filepath; + this.setWsChanged(false); + } + // ワークスペースが変更された・保存された + // ウィンドウタイトルバーテキストを変更 + setWsChanged(changed) { + let title; + this.wsChanged = changed; + if (this.saveFilepath) title = this.saveFilepath + ' - ' + ugj_const.app_name; + else title = ugj_const.app_name; + if (changed) title = '*' + title; + this.ipcRenderer.send('set_title', title); + } + // 保存ファイルプロパティを更新 + newFile() { this.setSaveFilepath(null); } + // ワークスペースファイル読み込みの一連の動作のラッパ + async loadWsFile() { + let filepath = await this.openFile('xml', ugj_const.doc_root); + if (filepath.length > 0) { + if (this.saveFilepath === null) { + this.setSaveFilepath(filepath); + } //読み込みに失敗してもsaveFilepathが更新されてしまうのはちょっと具合が悪いかも + return this.readFromFile(filepath); + } else { + return ''; + } + } + // その他ファイル読み込みの一連の動作のラッパ + async loadFile(ext) { + let filepath = await this.openFile(ext, ugj_const.doc_root); + if (filepath.length > 0) { + return this.readFromFile(filepath); + } else { + return ''; + } + } + async selectMascotFile() { + return await this.openFile('png', ugj_const.mascot_path); + } + // オープンファイルダイアログ + async openFile(ext, dpath) { + let title = 'Select a file'; + let filter; + if (ext == 'xml') { + filter = { name: 'XML - Extensible Markup Language', extensions: ['xml'] }; + } else if (ext == 'js') { + filter = { name: 'JS - JavaScript', extensions: ['js'] }; + } else if (ext == 'png') { + filter = { name: 'PNG - Portable Network Graphics', extensions: ['png'] }; + } else { + filter = { name: 'text file', extensions: ['txt'] }; + } + let filepaths = await this.ipcRenderer.invoke('open_dialog', title, dpath, filter); + if (filepaths == undefined) { + return ''; + } else { + return filepaths[0]; + } + } + // ファイルからデータを読み込み + readFromFile(filepath) { + let data = ''; + try { + data = this.fs.readFileSync(filepath, 'utf-8'); + } + catch (err) { + console.log(err); + } + return data; + } + // テキストファイル読み込み: 外部スクリプト動的読み込みに使用 + readTextFile(filepath) { + return this.readFromFile(filepath); + } + // ワークスペースファイル保存の一連の動作のラッパ + async saveWsFile(data) { + if (this.saveFilepath === null) { + let filepath = await this.selectSaveFile('xml'); + if (filepath === undefined) { //キャンセル + return undefined; + } else { + this.setSaveFilepath(filepath); + } //これも保存が成功したら変更するようにすべきかしら + } else this.setWsChanged(false); + return this.writeToFile(this.saveFilepath, data); + } + // その他ファイル保存の一連の動作のラッパ + async saveFile(data, ext) { + let filepath = await this.selectSaveFile(ext); + if (filepath === undefined) { //キャンセル + return undefined; + } + return this.writeToFile(filepath, data); + } + // ファイル保存ダイアログ + async selectSaveFile(ext) { + let title = '保存先を決定してください'; + let filter, filter_name; + let defName; + if (ext == 'xml') { + filter = { name: 'xml file', extensions: ['xml'] }; + defName = this.getUniqueFilepath() + '.xml'; + } else if (ext == 'js' || ext == 'py') { + if (ext == 'js') filter_name = 'javascript file'; + else filter_name = 'python file' + filter = { name: filter_name, extensions: [ext] }; + // ワークスペース保存名がある場合、それをベースにファイル名の候補を決める + if (this.saveFilepath === null) { + defName = this.getUniqueFilepath() + '.' + ext; + } else { + let dirname = this.path.dirname(this.saveFilepath); + let basename = this.path.basename(this.saveFilepath, '.xml'); + defName = path.join(dirname, basename) + '.' + ext; + } + } else { + filter = { name: 'text file', extensions: ['txt'] }; + } + let filename = await this.ipcRenderer.invoke('save_dialog', title, defName, filter); + return filename; + } + // ファイル書き込み + writeToFile(filepath, data) { + try { + this.fs.writeFileSync(filepath, data); + return true; + } + catch (err) { + return false; + } + } + + // 子プロセス関連 + // 新しい子プロセスを作成し、配列に保存 + addChild(child) { + this.children.push(child); + } + // 全ての子プロセスを殺し、配列をクリア + killAllChildren() { + this.children.forEach(function (child) { + child.kill(); + }); + this.children = []; + } + + // 設定(保存ファイルパスと未保存フラグ)をローカルストレージに保存 + savePrefsToLS() { + let wc = '0'; + if (this.wsChanged) wc = '1'; + let o = { 'saveFilepath': this.saveFilepath, 'wsChanged': wc, 'mascotFilePath': this.mascotFilePath }; + let s = JSON.stringify(o); + localStorage.setItem(this.localStorage_fname, s); + } + + // 設定(保存ファイルパスと未保存フラグ)をローカルストレージからロード + loadPrefsFromLS() { + let s = localStorage.getItem(this.localStorage_fname); + if (s !== null) { + let o = JSON.parse(s); + this.setSaveFilepath(o.saveFilepath); + if (o.wsChanged == '0') this.setWsChanged(false); + else this.setWsChanged(true); + if (o.mascotFilePath) this.setMascotFilePath(o.mascotFilePath); + } + } + + // マスコット画像パスをプロパティにセット + setMascotFilePath(fpath) { + this.mascotFilePath = fpath; + } + getMascotFilePath() { + return this.mascotFilePath; + } + + + // ファイル名にアプリケーションのドキュメントルートまでのパスをつけて返す + getDocPath(filename) { + return this.path.join(this.appDocRoot, filename); + } + +} +// ブラウザ動作用 +class brUtil { + // マスコット + getMascotFilePath() { return `./img/${ugj_const.mascot_defname}`; } + //ワークスペースのダウンロード + saveWsFile(xml_text) { + let blob = new Blob([xml_text], { "type": "text/xml" }); + const downLoadLink = document.createElement("a"); + document.body.appendChild(downLoadLink); + downLoadLink.download = 'workspace.xml'; + downLoadLink.href = URL.createObjectURL(blob); + downLoadLink.click(); + downLoadLink.parentElement.removeChild(downLoadLink); + return true; + } + //ワークスペースのインポート + loadWsFile() { + const fileInputEl = document.createElement('input'); + document.body.appendChild(fileInputEl); + fileInputEl.type = 'file'; + fileInputEl.addEventListener('change', ev => { + let reader = new FileReader(); + reader.readAsText(ev.target.files[0]); + reader.addEventListener('load', () => { + let xml = Blockly.Xml.textToDom(reader.result); + Blockly.Xml.domToWorkspace(xml, workspace); + }); + }); + fileInputEl.click(); + fileInputEl.parentElement.removeChild(fileInputEl); + return ''; + } + + // index.jsから万一呼ばれても何もしない関数 + openURL() { ; } + selectMascotFile() { ; } + setMascotFilePath(fname) { ; } + saveFile() { ; } + savePrefsToLS() { ; } + loadPrefsFromLS() { ; } + newFile() { ; } + setWsChanged() { ; } + killAllChildren() { ; } +} + +// Electron 動作 / ブラウザ動作自動判別 +const is_el = (typeof window.ocogeapi !== 'undefined') + +// utilクラスのインスタンスを返す +const elUtil_new = () => { + if (is_el) return new elUtil + else return new brUtil +} + +// "require" for "BLOCK"s +// ブラウザ動作時にはすべてアラートを表示 +const require = module_name => { + if (is_el) { + switch (module_name) { + case '@ocogeclub/lgpio': + return window.ocogeapi.lgpio; + case '@ocogeclub/bme280': + return window.ocogeapi.bme280; + case 'fs': + return window.ocogeapi.fs; + case 'path': + return window.ocogeapi.path; + default: + throw new Error(`Unknown module "${module_name}" required.\nStopped.`); + } + } else { + let block; + switch (module_name) { + case '@ocogeclub/lgpio': + block = 'GPIO'; + break; + case '@ocogeclub/bme280': + block = 'BME280'; + break; + case 'fs': + block = 'ファイル'; + break; + default: + throw new Error(ugj_const.error_ja_all); + } + throw `ブロック「${block}」は、Web体験版ではご利用になれません。\n詳しくは https://ocoge.club/ をご覧ください。`; + } +} diff --git a/lib/models/face_landmark_68_tiny_model-weights_manifest.json b/lib/models/face_landmark_68_tiny_model-weights_manifest.json new file mode 100644 index 0000000..83de57b --- /dev/null +++ b/lib/models/face_landmark_68_tiny_model-weights_manifest.json @@ -0,0 +1,39 @@ +[ + { + "weights": + [ + {"name":"dense0/conv0/filters","shape":[3,3,3,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008194216092427571,"min":-0.9423348506291708}}, + {"name":"dense0/conv0/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006839508168837603,"min":-0.8412595047670252}}, + {"name":"dense0/conv1/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009194007106855804,"min":-1.2779669878529567}}, + {"name":"dense0/conv1/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0036026100317637128,"min":-0.3170296827952067}}, + {"name":"dense0/conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.000740380117706224,"min":-0.06367269012273527}}, + {"name":"dense0/conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":1,"min":0}}, + {"name":"dense0/conv2/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":1,"min":0}}, + {"name":"dense0/conv2/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0037702228508743585,"min":-0.6220867703942692}}, + {"name":"dense1/conv0/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0033707996209462483,"min":-0.421349952618281}}, + {"name":"dense1/conv0/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014611541991140328,"min":-1.8556658328748217}}, + {"name":"dense1/conv0/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002832523046755323,"min":-0.30307996600281956}}, + {"name":"dense1/conv1/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006593170586754294,"min":-0.6329443763284123}}, + {"name":"dense1/conv1/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.012215249211180444,"min":-1.6001976466646382}}, + {"name":"dense1/conv1/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002384825547536214,"min":-0.3028728445370992}}, + {"name":"dense1/conv2/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005859645441466687,"min":-0.7617539073906693}}, + {"name":"dense1/conv2/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013121426806730382,"min":-1.7845140457153321}}, + {"name":"dense1/conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0032247188044529336,"min":-0.46435950784122243}}, + {"name":"dense2/conv0/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002659512618008782,"min":-0.32977956463308894}}, + {"name":"dense2/conv0/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015499923743453681,"min":-1.9839902391620712}}, + {"name":"dense2/conv0/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0032450980999890497,"min":-0.522460794098237}}, + {"name":"dense2/conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005911862382701799,"min":-0.792189559282041}}, + {"name":"dense2/conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021025861478319356,"min":-2.2077154552235325}}, + {"name":"dense2/conv1/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00349616945958605,"min":-0.46149436866535865}}, + {"name":"dense2/conv2/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008104994250278847,"min":-1.013124281284856}}, + {"name":"dense2/conv2/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.029337059282789044,"min":-3.5791212325002633}}, + {"name":"dense2/conv2/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0038808938334969913,"min":-0.4230174278511721}}, + {"name":"fc/weights","shape":[128,136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014016061670639936,"min":-1.8921683255363912}}, + {"name":"fc/bias","shape":[136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0029505149698724935,"min":0.088760145008564}} + ], + "paths": + [ + "face_landmark_68_tiny_model.bin" + ] + } +] \ No newline at end of file diff --git a/lib/models/face_landmark_68_tiny_model.bin b/lib/models/face_landmark_68_tiny_model.bin new file mode 100644 index 0000000000000000000000000000000000000000..f04a9d5ecd26eb59062ea72c6617a955af22cc5c GIT binary patch literal 77224 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 E2Vsdq&Hw-a literal 0 HcmV?d00001 diff --git a/lib/models/tiny_face_detector_model-weights_manifest.json b/lib/models/tiny_face_detector_model-weights_manifest.json index 7d3b222..d11c9a3 100644 --- a/lib/models/tiny_face_detector_model-weights_manifest.json +++ b/lib/models/tiny_face_detector_model-weights_manifest.json @@ -1 +1,30 @@ -[{"weights":[{"name":"conv0/filters","shape":[3,3,3,16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009007044399485869,"min":-1.2069439495311063}},{"name":"conv0/bias","shape":[16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005263455241334205,"min":-0.9211046672334858}},{"name":"conv1/depthwise_filter","shape":[3,3,16,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004001977630690033,"min":-0.5042491814669441}},{"name":"conv1/pointwise_filter","shape":[1,1,16,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013836609615999109,"min":-1.411334180831909}},{"name":"conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0015159862590771096,"min":-0.30926119685173037}},{"name":"conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002666276225856706,"min":-0.317286870876948}},{"name":"conv2/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015265831292844286,"min":-1.6792414422128714}},{"name":"conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0020280554598453,"min":-0.37113414915168985}},{"name":"conv3/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006100742489683862,"min":-0.8907084034938438}},{"name":"conv3/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.016276211832083907,"min":-2.0508026908425725}},{"name":"conv3/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003394414279975143,"min":-0.7637432129944072}},{"name":"conv4/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006716050119961009,"min":-0.8059260143953211}},{"name":"conv4/pointwise_filter","shape":[1,1,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021875603993733724,"min":-2.8875797271728514}},{"name":"conv4/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0041141652009066415,"min":-0.8187188749804216}},{"name":"conv5/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008423839597141042,"min":-0.9013508368940915}},{"name":"conv5/pointwise_filter","shape":[1,1,256,512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.030007277283014035,"min":-3.8709387695088107}},{"name":"conv5/bias","shape":[512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008402082966823203,"min":-1.4871686851277068}},{"name":"conv8/filters","shape":[1,1,512,25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.028336129469030042,"min":-4.675461362389957}},{"name":"conv8/bias","shape":[25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002268134028303857,"min":-0.41053225912299807}}],"paths":["tiny_face_detector_model-shard1"]}] \ No newline at end of file +[ + { + "weights": + [ + {"name":"conv0/filters","shape":[3,3,3,16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009007044399485869,"min":-1.2069439495311063}}, + {"name":"conv0/bias","shape":[16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005263455241334205,"min":-0.9211046672334858}}, + {"name":"conv1/depthwise_filter","shape":[3,3,16,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004001977630690033,"min":-0.5042491814669441}}, + {"name":"conv1/pointwise_filter","shape":[1,1,16,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013836609615999109,"min":-1.411334180831909}}, + {"name":"conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0015159862590771096,"min":-0.30926119685173037}}, + {"name":"conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002666276225856706,"min":-0.317286870876948}}, + {"name":"conv2/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015265831292844286,"min":-1.6792414422128714}}, + {"name":"conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0020280554598453,"min":-0.37113414915168985}}, + {"name":"conv3/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006100742489683862,"min":-0.8907084034938438}}, + {"name":"conv3/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.016276211832083907,"min":-2.0508026908425725}}, + {"name":"conv3/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003394414279975143,"min":-0.7637432129944072}}, + {"name":"conv4/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006716050119961009,"min":-0.8059260143953211}}, + {"name":"conv4/pointwise_filter","shape":[1,1,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021875603993733724,"min":-2.8875797271728514}}, + {"name":"conv4/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0041141652009066415,"min":-0.8187188749804216}}, + {"name":"conv5/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008423839597141042,"min":-0.9013508368940915}}, + {"name":"conv5/pointwise_filter","shape":[1,1,256,512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.030007277283014035,"min":-3.8709387695088107}}, + {"name":"conv5/bias","shape":[512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008402082966823203,"min":-1.4871686851277068}}, + {"name":"conv8/filters","shape":[1,1,512,25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.028336129469030042,"min":-4.675461362389957}}, + {"name":"conv8/bias","shape":[25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002268134028303857,"min":-0.41053225912299807}} + ], + "paths": + [ + "tiny_face_detector_model.bin" + ] + } +] \ No newline at end of file diff --git a/lib/models/tiny_face_detector_model-shard1 b/lib/models/tiny_face_detector_model.bin similarity index 100% rename from lib/models/tiny_face_detector_model-shard1 rename to lib/models/tiny_face_detector_model.bin diff --git a/local_modules/@ocogeclub/bme280/BME280.js b/local_modules/@ocogeclub/bme280/BME280.js index e69f369..d35238b 100644 --- a/local_modules/@ocogeclub/bme280/BME280.js +++ b/local_modules/@ocogeclub/bme280/BME280.js @@ -1,269 +1,266 @@ 'use strict'; -// const { strictEqual } = require('assert'); +this.pi = null; -class BME280 { +this.i2cBusNo = null; +this.i2cAddress = null; +this.i2cHand = null; - constructor(options) { - this.pi = require('@ocogeclub/lgpio'); +this.I2C_ADDRESS_B = 0x76; +this.I2C_ADDRESS_A = 0x77; +this.CHIP_ID = 0x58; - this.i2cBusNo = (options && options.hasOwnProperty('i2cBusNo')) ? options.i2cBusNo : 1; - this.i2cAddress = (options && options.hasOwnProperty('i2cAddress')) ? options.i2cAddress : BME280.BME280_DEFAULT_I2C_ADDRESS(); - this.i2cHand = this.pi.i2c_open(this.i2cBusNo, this.i2cAddress); +this.REGISTER_DIG_T1 = 0x88; +this.REGISTER_DIG_T2 = 0x8A; +this.REGISTER_DIG_T3 = 0x8C; - this.I2C_ADDRESS_B = 0x76; - this.I2C_ADDRESS_A = 0x77; - this.CHIP_ID = 0x58; +this.REGISTER_DIG_P1 = 0x8E; +this.REGISTER_DIG_P2 = 0x90; +this.REGISTER_DIG_P3 = 0x92; +this.REGISTER_DIG_P4 = 0x94; +this.REGISTER_DIG_P5 = 0x96; +this.REGISTER_DIG_P6 = 0x98; +this.REGISTER_DIG_P7 = 0x9A; +this.REGISTER_DIG_P8 = 0x9C; +this.REGISTER_DIG_P9 = 0x9E; - this.REGISTER_DIG_T1 = 0x88; - this.REGISTER_DIG_T2 = 0x8A; - this.REGISTER_DIG_T3 = 0x8C; +this.REGISTER_DIG_H1 = 0xA1; +this.REGISTER_DIG_H2 = 0xE1; +this.REGISTER_DIG_H3 = 0xE3; +this.REGISTER_DIG_H4 = 0xE4; +this.REGISTER_DIG_H5 = 0xE5; +this.REGISTER_DIG_H6 = 0xE7; - this.REGISTER_DIG_P1 = 0x8E; - this.REGISTER_DIG_P2 = 0x90; - this.REGISTER_DIG_P3 = 0x92; - this.REGISTER_DIG_P4 = 0x94; - this.REGISTER_DIG_P5 = 0x96; - this.REGISTER_DIG_P6 = 0x98; - this.REGISTER_DIG_P7 = 0x9A; - this.REGISTER_DIG_P8 = 0x9C; - this.REGISTER_DIG_P9 = 0x9E; +this.REGISTER_CHIPID = 0xD0; +this.REGISTER_RESET = 0xE0; - this.REGISTER_DIG_H1 = 0xA1; - this.REGISTER_DIG_H2 = 0xE1; - this.REGISTER_DIG_H3 = 0xE3; - this.REGISTER_DIG_H4 = 0xE4; - this.REGISTER_DIG_H5 = 0xE5; - this.REGISTER_DIG_H6 = 0xE7; +this.REGISTER_CONTROL_HUM = 0xF2; +this.REGISTER_CONTROL = 0xF4; +this.REGISTER_PRESSURE_DATA = 0xF7; +this.REGISTER_TEMP_DATA = 0xFA; +this.REGISTER_HUMIDITY_DATA = 0xFD; - this.REGISTER_CHIPID = 0xD0; - this.REGISTER_RESET = 0xE0; +exports.init = (options) => { + this.pi = require('@ocogeclub/lgpio'); - this.REGISTER_CONTROL_HUM = 0xF2; - this.REGISTER_CONTROL = 0xF4; - this.REGISTER_PRESSURE_DATA = 0xF7; - this.REGISTER_TEMP_DATA = 0xFA; - this.REGISTER_HUMIDITY_DATA = 0xFD; + this.i2cBusNo = (options && options.hasOwnProperty('i2cBusNo')) ? options.i2cBusNo : 1; + this.i2cAddress = (options && options.hasOwnProperty('i2cAddress')) ? options.i2cAddress : this.BME280_DEFAULT_I2C_ADDRESS(); + this.i2cHand = this.pi.i2c_open(this.i2cBusNo, this.i2cAddress); + + let r; + r = this.pi.i2c_write_byte_data(this.i2cHand, this.REGISTER_CHIPID, 0); + if (r < 0) return r; + let chipId = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_CHIPID); + if (chipId !== this.CHIP_ID_BME280() && + chipId !== this.CHIP_ID1_BMP280() && + chipId !== this.CHIP_ID2_BMP280() && + chipId !== this.CHIP_ID3_BMP280()) { + return `Unexpected BMx280 chip ID: 0x${chipId.toString(16).toUpperCase()}`; } - - init() { - let r; - r = this.pi.i2c_write_byte_data(this.i2cHand, this.REGISTER_CHIPID, 0); - if (r < 0) return r; - let chipId = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_CHIPID); - if (chipId !== BME280.CHIP_ID_BME280() && - chipId !== BME280.CHIP_ID1_BMP280() && - chipId !== BME280.CHIP_ID2_BMP280() && - chipId !== BME280.CHIP_ID3_BMP280()) { - return `Unexpected BMx280 chip ID: 0x${chipId.toString(16).toUpperCase()}`; + // console.log(`Found BMx280 chip ID 0x${chipId.toString(16).toUpperCase()} on bus i2c-${this.i2cBusNo}, address 0x${this.i2cAddress.toString(16).toUpperCase()}`); + this.loadCalibration((err) => { + if (err) { + return err; } - // console.log(`Found BMx280 chip ID 0x${chipId.toString(16).toUpperCase()} on bus i2c-${this.i2cBusNo}, address 0x${this.i2cAddress.toString(16).toUpperCase()}`); - this.loadCalibration((err) => { - if (err) { - return err; - } - // Humidity 16x oversampling - // - let r = this.pi.i2c_write_byte_data(this.i2cHand, this.REGISTER_CONTROL_HUM, 0b00000101); - if (r < 0) return `Humidity 16x oversampling error: ${r}`; - // Temperture/pressure 16x oversampling, normal mode - // - r = this.pi.i2c_write_byte_data(this.i2cHand, this.REGISTER_CONTROL, 0b10110111); - if (r < 0) return `Temperture/pressure 16x oversampling error: ${r}`; - - return 0; - }); - } - - // reset() - // - // Perform a power-on reset procedure. You will need to call init() following a reset() - // - reset() { - const POWER_ON_RESET_CMD = 0xB6; - let r = this.pi.i2c_write_byte_data(this.i2cHand, this.REGISTER_RESET, POWER_ON_RESET_CMD); - if (r < 0) return `cannot power-on reset: ${r}`; - else return 0; - } - - // cancel() - // - // Cancels the sensor and releases resources. - // - cancel() { - if (this.i2cHand >= 0) { - this.pi.i2c_close(this.i2cHand); - this.i2cHand = 0; - } - } - - readSensorData() { - if (!this.cal) { - return 'You must first call bme280.init()'; - } - - // Grab temperature, humidity, and pressure in a single read + // Humidity 16x oversampling // - let buffer = this.pi.i2c_read_i2c_block_data(this.i2cHand, this.REGISTER_PRESSURE_DATA, 8); - if (!buffer) return `couldn't grab data`; - // Temperature (temperature first since we need t_fine for pressure and humidity) + let r = this.pi.i2c_write_byte_data(this.i2cHand, this.REGISTER_CONTROL_HUM, 0b00000101); + if (r < 0) return `Humidity 16x oversampling error: ${r}`; + // Temperture/pressure 16x oversampling, normal mode // - let adc_T = BME280.uint20(buffer[3], buffer[4], buffer[5]); - let tvar1 = ((((adc_T >> 3) - (this.cal.dig_T1 << 1))) * this.cal.dig_T2) >> 11; - let tvar2 = (((((adc_T >> 4) - this.cal.dig_T1) * ((adc_T >> 4) - this.cal.dig_T1)) >> 12) * this.cal.dig_T3) >> 14; - let t_fine = tvar1 + tvar2; - - let temperature_C = ((t_fine * 5 + 128) >> 8) / 100; - - // Pressure - // - let adc_P = BME280.uint20(buffer[0], buffer[1], buffer[2]); - let pvar1 = t_fine / 2 - 64000; - let pvar2 = pvar1 * pvar1 * this.cal.dig_P6 / 32768; - pvar2 = pvar2 + pvar1 * this.cal.dig_P5 * 2; - pvar2 = pvar2 / 4 + this.cal.dig_P4 * 65536; - pvar1 = (this.cal.dig_P3 * pvar1 * pvar1 / 524288 + this.cal.dig_P2 * pvar1) / 524288; - pvar1 = (1 + pvar1 / 32768) * this.cal.dig_P1; - - let pressure_hPa = 0; - - if (pvar1 !== 0) { - let p = 1048576 - adc_P; - p = ((p - pvar2 / 4096) * 6250) / pvar1; - pvar1 = this.cal.dig_P9 * p * p / 2147483648; - pvar2 = p * this.cal.dig_P8 / 32768; - p = p + (pvar1 + pvar2 + this.cal.dig_P7) / 16; - - pressure_hPa = p / 100; - } - - // Humidity (available on the BME280, will be zero on the BMP280 since it has no humidity sensor) - // - let adc_H = BME280.uint16(buffer[6], buffer[7]); - - let h = t_fine - 76800; - h = (adc_H - (this.cal.dig_H4 * 64 + this.cal.dig_H5 / 16384 * h)) * - (this.cal.dig_H2 / 65536 * (1 + this.cal.dig_H6 / 67108864 * h * (1 + this.cal.dig_H3 / 67108864 * h))); - h = h * (1 - this.cal.dig_H1 * h / 524288); - - let humidity = (h > 100) ? 100 : (h < 0 ? 0 : h); - - return { - temperature_C: temperature_C, - humidity: humidity, - pressure_hPa: pressure_hPa - }; - } - - loadCalibration(callback) { - let buffer = this.pi.i2c_read_i2c_block_data(this.i2cHand, this.REGISTER_DIG_T1, 24); - // for (let i = 0; i < 24; i++) console.log(parseInt(buffer[i], 16)); - if (buffer) { - let h1 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H1); - let h2 = this.pi.i2c_read_word_data(this.i2cHand, this.REGISTER_DIG_H2); - let h3 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H3); - let h4 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H4); - let h5 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H5); - let h5_1 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H5 + 1); - let h6 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H6); - - this.cal = { - dig_T1: BME280.uint16(buffer[1], buffer[0]), - dig_T2: BME280.int16(buffer[3], buffer[2]), - dig_T3: BME280.int16(buffer[5], buffer[4]), - - dig_P1: BME280.uint16(buffer[7], buffer[6]), - dig_P2: BME280.int16(buffer[9], buffer[8]), - dig_P3: BME280.int16(buffer[11], buffer[10]), - dig_P4: BME280.int16(buffer[13], buffer[12]), - dig_P5: BME280.int16(buffer[15], buffer[14]), - dig_P6: BME280.int16(buffer[17], buffer[16]), - dig_P7: BME280.int16(buffer[19], buffer[18]), - dig_P8: BME280.int16(buffer[21], buffer[20]), - dig_P9: BME280.int16(buffer[23], buffer[22]), - - dig_H1: h1, - dig_H2: h2, - dig_H3: h3, - dig_H4: (h4 << 4) | (h5 & 0xF), - dig_H5: (h5_1 << 4) | (h5 >> 4), - dig_H6: h6 - }; - - // console.log('BME280 cal = ' + JSON.stringify(this.cal, null, 2)); - callback(); - } - } - - static BME280_DEFAULT_I2C_ADDRESS() { - return 0x77; - } - - static CHIP_ID1_BMP280() { - return 0x56; - } - - static CHIP_ID2_BMP280() { - return 0x57; - } - - static CHIP_ID3_BMP280() { - return 0x58; - } - - static CHIP_ID_BME280() { - return 0x60; - } - - static int16(msb, lsb) { - let val = BME280.uint16(msb, lsb); - return val > 32767 ? (val - 65536) : val; - } - - static uint16(msb, lsb) { - return msb << 8 | lsb; - } - - static uint20(msb, lsb, xlsb) { - return ((msb << 8 | lsb) << 8 | xlsb) >> 4; - } - - static convertCelciusToFahrenheit(c) { - return c * 9 / 5 + 32; - } - - static convertHectopascalToInchesOfMercury(hPa) { - return hPa * 0.02952998751; - } - - static convertMetersToFeet(m) { - return m * 3.28084; - } - - static calculateHeatIndexCelcius(temperature_C, humidity) { - return -8.784695 + 1.61139411 * temperature_C + 2.33854900 * humidity + - -0.14611605 * temperature_C * humidity + -0.01230809 * Math.pow(temperature_C, 2) + - -0.01642482 * Math.pow(humidity, 2) + 0.00221173 * Math.pow(temperature_C, 2) * humidity + - 0.00072546 * temperature_C * Math.pow(humidity, 2) + - -0.00000358 * Math.pow(temperature_C, 2) * Math.pow(humidity, 2); - } - - static calculateDewPointCelcius(temperature_C, humidity) { - return 243.04 * (Math.log(humidity / 100.0) + ((17.625 * temperature_C) / (243.04 + temperature_C))) / - (17.625 - Math.log(humidity / 100.0) - ((17.625 * temperature_C) / (243.04 + temperature_C))); - } - - static calculateAltitudeMeters(pressure_hPa, seaLevelPressure_hPa) { - if (!seaLevelPressure_hPa) { - seaLevelPressure_hPa = 1013.25; - } - - return (1.0 - Math.pow(pressure_hPa / seaLevelPressure_hPa, (1 / 5.2553))) * 145366.45 * 0.3048; - } + r = this.pi.i2c_write_byte_data(this.i2cHand, this.REGISTER_CONTROL, 0b10110111); + if (r < 0) return `Temperture/pressure 16x oversampling error: ${r}`; + return 0; + }); +} + +// reset() +// +// Perform a power-on reset procedure. You will need to call init() following a reset() +// +exports.reset = () => { + const POWER_ON_RESET_CMD = 0xB6; + let r = this.pi.i2c_write_byte_data(this.i2cHand, this.REGISTER_RESET, POWER_ON_RESET_CMD); + if (r < 0) return `cannot power-on reset: ${r}`; + else return 0; +} + +// cancel() +// +// Cancels the sensor and releases resources. +// +exports.cancel = () => { + if (this.i2cHand >= 0) { + this.pi.i2c_close(this.i2cHand); + this.i2cHand = 0; + } +} + +exports.readSensorData = () => { + if (!this.cal) { + return 'You must first call bme280.init()'; + } + + // Grab temperature, humidity, and pressure in a single read + // + let buffer = this.pi.i2c_read_i2c_block_data(this.i2cHand, this.REGISTER_PRESSURE_DATA, 8); + if (!buffer) return `couldn't grab data`; + // Temperature (temperature first since we need t_fine for pressure and humidity) + // + let adc_T = this.uint20(buffer[3], buffer[4], buffer[5]); + let tvar1 = ((((adc_T >> 3) - (this.cal.dig_T1 << 1))) * this.cal.dig_T2) >> 11; + let tvar2 = (((((adc_T >> 4) - this.cal.dig_T1) * ((adc_T >> 4) - this.cal.dig_T1)) >> 12) * this.cal.dig_T3) >> 14; + let t_fine = tvar1 + tvar2; + + let temperature_C = ((t_fine * 5 + 128) >> 8) / 100; + + // Pressure + // + let adc_P = this.uint20(buffer[0], buffer[1], buffer[2]); + let pvar1 = t_fine / 2 - 64000; + let pvar2 = pvar1 * pvar1 * this.cal.dig_P6 / 32768; + pvar2 = pvar2 + pvar1 * this.cal.dig_P5 * 2; + pvar2 = pvar2 / 4 + this.cal.dig_P4 * 65536; + pvar1 = (this.cal.dig_P3 * pvar1 * pvar1 / 524288 + this.cal.dig_P2 * pvar1) / 524288; + pvar1 = (1 + pvar1 / 32768) * this.cal.dig_P1; + + let pressure_hPa = 0; + + if (pvar1 !== 0) { + let p = 1048576 - adc_P; + p = ((p - pvar2 / 4096) * 6250) / pvar1; + pvar1 = this.cal.dig_P9 * p * p / 2147483648; + pvar2 = p * this.cal.dig_P8 / 32768; + p = p + (pvar1 + pvar2 + this.cal.dig_P7) / 16; + + pressure_hPa = p / 100; + } + + // Humidity (available on the BME280, will be zero on the BMP280 since it has no humidity sensor) + // + let adc_H = this.uint16(buffer[6], buffer[7]); + + let h = t_fine - 76800; + h = (adc_H - (this.cal.dig_H4 * 64 + this.cal.dig_H5 / 16384 * h)) * + (this.cal.dig_H2 / 65536 * (1 + this.cal.dig_H6 / 67108864 * h * (1 + this.cal.dig_H3 / 67108864 * h))); + h = h * (1 - this.cal.dig_H1 * h / 524288); + + let humidity = (h > 100) ? 100 : (h < 0 ? 0 : h); + + return { + temperature_C: temperature_C, + humidity: humidity, + pressure_hPa: pressure_hPa + }; +} + +exports.loadCalibration = (callback) => { + let buffer = this.pi.i2c_read_i2c_block_data(this.i2cHand, this.REGISTER_DIG_T1, 24); + // for (let i = 0; i < 24; i++) console.log(parseInt(buffer[i], 16)); + if (buffer) { + let h1 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H1); + let h2 = this.pi.i2c_read_word_data(this.i2cHand, this.REGISTER_DIG_H2); + let h3 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H3); + let h4 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H4); + let h5 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H5); + let h5_1 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H5 + 1); + let h6 = this.pi.i2c_read_byte_data(this.i2cHand, this.REGISTER_DIG_H6); + + this.cal = { + dig_T1: this.uint16(buffer[1], buffer[0]), + dig_T2: this.int16(buffer[3], buffer[2]), + dig_T3: this.int16(buffer[5], buffer[4]), + + dig_P1: this.uint16(buffer[7], buffer[6]), + dig_P2: this.int16(buffer[9], buffer[8]), + dig_P3: this.int16(buffer[11], buffer[10]), + dig_P4: this.int16(buffer[13], buffer[12]), + dig_P5: this.int16(buffer[15], buffer[14]), + dig_P6: this.int16(buffer[17], buffer[16]), + dig_P7: this.int16(buffer[19], buffer[18]), + dig_P8: this.int16(buffer[21], buffer[20]), + dig_P9: this.int16(buffer[23], buffer[22]), + + dig_H1: h1, + dig_H2: h2, + dig_H3: h3, + dig_H4: (h4 << 4) | (h5 & 0xF), + dig_H5: (h5_1 << 4) | (h5 >> 4), + dig_H6: h6 + }; + + // console.log('BME280 cal = ' + JSON.stringify(this.cal, null, 2)); + callback(); + } +} + +exports.BME280_DEFAULT_I2C_ADDRESS = () => { + return 0x77; +} + +exports.CHIP_ID1_BMP280 = () => { + return 0x56; +} + +exports.CHIP_ID2_BMP280 = () => { + return 0x57; +} + +exports.CHIP_ID3_BMP280 = () => { + return 0x58; +} + +exports.CHIP_ID_BME280 = () => { + return 0x60; +} + +exports.int16 = (msb, lsb) => { + let val = this.uint16(msb, lsb); + return val > 32767 ? (val - 65536) : val; +} + +exports.uint16 = (msb, lsb) => { + return msb << 8 | lsb; +} + +exports.uint20 = (msb, lsb, xlsb) => { + return ((msb << 8 | lsb) << 8 | xlsb) >> 4; +} + +exports.convertCelciusToFahrenheit = (c) => { + return c * 9 / 5 + 32; +} + +exports.convertHectopascalToInchesOfMercury = (hPa) => { + return hPa * 0.02952998751; +} + +exports.convertMetersToFeet = (m) => { + return m * 3.28084; +} + +exports.calculateHeatIndexCelcius = (temperature_C, humidity) => { + return -8.784695 + 1.61139411 * temperature_C + 2.33854900 * humidity + + -0.14611605 * temperature_C * humidity + -0.01230809 * Math.pow(temperature_C, 2) + + -0.01642482 * Math.pow(humidity, 2) + 0.00221173 * Math.pow(temperature_C, 2) * humidity + + 0.00072546 * temperature_C * Math.pow(humidity, 2) + + -0.00000358 * Math.pow(temperature_C, 2) * Math.pow(humidity, 2); +} + +exports.calculateDewPointCelcius = (temperature_C, humidity) => { + return 243.04 * (Math.log(humidity / 100.0) + ((17.625 * temperature_C) / (243.04 + temperature_C))) / + (17.625 - Math.log(humidity / 100.0) - ((17.625 * temperature_C) / (243.04 + temperature_C))); +} + +exports.calculateAltitudeMeters = (pressure_hPa, seaLevelPressure_hPa) => { + if (!seaLevelPressure_hPa) { + seaLevelPressure_hPa = 1013.25; + } + + return (1.0 - Math.pow(pressure_hPa / seaLevelPressure_hPa, (1 / 5.2553))) * 145366.45 * 0.3048; } -module.exports = BME280; /* * This code was forked from skylarstein's bme280-sensor: https://github.com/skylarstein/bme280-sensor diff --git a/main.js b/main.js new file mode 100644 index 0000000..c61c4e3 --- /dev/null +++ b/main.js @@ -0,0 +1,178 @@ +const { app, BrowserWindow, Menu, session, ipcMain, dialog } = require('electron') +const path = require('path') + +/** Force disable security warning */ +process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true' + +// Keep a global reference of the window object, if you don't, the window will +// be closed automatically when the JavaScript object is garbage collected. +let win + +function createWindow() { + // Create the browser window. + win = new BrowserWindow({ + /** Icon */ + icon: "./icon.png", + width: 1280, + height: 940, + webPreferences: { + preload: path.join(__dirname, 'preload.js') + // nodeIntegration: true, + // contextIsolation: false + } + }) + /** Maximize Window at startup */ + win.maximize() + + // and load the index.html of the app. + win.loadFile('index.html') + + // Open the DevTools. + win.webContents.openDevTools() + + // Emitted when the window is closed. + // win.on('closed', () => { + // // Dereference the window object, usually you would store windows + // // in an array if your app supports multi windows, this is the time + // // when you should delete the corresponding element. + // win = null + // }) + + /** For SkyWay */ + session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => { + details.requestHeaders['Origin'] = 'electron://localhost' + callback({ + cancel: false, + requestHeaders: details.requestHeaders + }) + }) +} + +// This method will be called when Electron has finished +// initialization and is ready to create browser windows. +// Some APIs can only be used after this event occurs. +// app.on('ready', createWindow) +app.whenReady().then(() => { + createWindow() + + app.on('activate', function () { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (BrowserWindow.getAllWindows().length === 0) createWindow() + }) + + /** Custom Menu */ + let template = [ + { + label: 'Menu', + submenu: [ + { + label: 'Toggle Menu Bar', + click: () => { + win.setMenuBarVisibility(!win.menuBarVisible) + }, + accelerator: "CommandOrControl+Shift+M" + }, + { + label: 'Reload', + click: () => { + win.reload() + }, + accelerator: "F5" + }, + { + label: 'Mascot', + click: (item, focusedWindow) => { + if (focusedWindow) + focusedWindow.webContents.executeJavaScript('ugj_selectMascot()') + }, + accelerator: "CommandOrControl+M" + }, + { + label: 'Toggle Developer Tools', + click: () => { + win.webContents.toggleDevTools() + }, + accelerator: "F12" + }, + { + label: 'About', + click: () => { + var os = require('os') + var detail = 'Version: ' + process.env.npm_package_version + '\n' + + 'Node.js: ' + process.versions.node + '\n' + + 'Chrome: ' + process.versions.chrome + '\n' + + 'Electron: ' + process.versions.electron + '\n' + + 'V8: ' + process.versions.v8 + '\n' + + 'OS: ' + os.type + ' ' + os.arch + ' ' + os.version + ' ' + os.release + var options = { + type: 'info', + buttons: ['OK'], + title: 'OCoGe', + message: 'OCoGe - Oiwa Code Generator', + detail: detail + } + require('electron').dialog.showMessageBox(win, options) + }, + accelerator: "CommandOrControl+I" + }, + { + label: 'Quit', + click: () => { + app.quit() + }, + accelerator: "CommandOrControl+Q" + } + ] + } + ] + const menu = Menu.buildFromTemplate(template) + Menu.setApplicationMenu(menu) + win.setMenuBarVisibility(false) +}) + + +// Quit when all windows are closed. +app.on('window-all-closed', () => { + // On macOS it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== 'darwin') { + app.quit() + } +}) + +// app.on('activate', () => { +// // On macOS it's common to re-create a window in the app when the +// // dock icon is clicked and there are no other windows open. +// if (win === null) { +// createWindow() +// } +// }) + +// In this file you can include the rest of your app's specific main process +// code. You can also put them in separate files and require them here. + +// IPC +ipcMain.on('set_title', (ev, title) => { + win.setTitle(title) +}) +ipcMain.handle('open_dialog', (ev, title, dpath, filter) => { + let filepaths = dialog.showOpenDialogSync(win, { + properties: ['openFile'], + title: title, + defaultPath: dpath, + filters: [ + filter + ] + }) + return filepaths +}) +ipcMain.handle('save_dialog', (ev, title, defName, filter) => { + let filename = dialog.showSaveDialogSync(win, { + title: title, + defaultPath: defName, + filters: [filter] + }) + console.log(filename) + return filename +}) diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 2559358..0000000 --- a/package-lock.json +++ /dev/null @@ -1,2252 +0,0 @@ -{ - "name": "ocoge", - "version": "0.1.3", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@electron/get": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.13.0.tgz", - "integrity": "sha512-+SjZhRuRo+STTO1Fdhzqnv9D2ZhjxXP6egsJ9kiO8dtP68cDx7dFCwWi64dlMQV7sWcfW1OYCW4wviEBzmRsfQ==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "global-agent": "^2.0.2", - "global-tunnel-ng": "^2.7.1", - "got": "^9.6.0", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - } - }, - "@electron/remote": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@electron/remote/-/remote-1.2.1.tgz", - "integrity": "sha512-yKh60I8KjezQkZqeuN5Nu2O/Z72+tgNgzvAa8QQPLtQbsrCOaeIWdXZQqierz4jQ5jzTNUk6KIcK3V2kFeaxaQ==" - }, - "@gar/promisify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", - "integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==", - "dev": true - }, - "@malept/cross-spawn-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", - "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "@npmcli/fs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.0.0.tgz", - "integrity": "sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==", - "dev": true, - "requires": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "@ocogeclub/bme280": { - "version": "file:local_modules/@ocogeclub/bme280" - }, - "@ocogeclub/lgpio": { - "version": "file:local_modules/@ocogeclub/lgpio", - "requires": { - "bindings": "^1.5.0", - "node-addon-api": "^1.7.1" - } - }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "requires": { - "defer-to-connect": "^1.0.1" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/cacheable-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", - "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "*", - "@types/keyv": "*", - "@types/node": "*", - "@types/responselike": "*" - } - }, - "@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true - }, - "@types/keyv": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", - "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/node": { - "version": "14.17.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.14.tgz", - "integrity": "sha512-rsAj2u8Xkqfc332iXV12SqIsjVi07H479bOP4q94NAcjzmAvapumEhuVIt53koEf7JFrpjgNKjBga5Pnn/GL8A==", - "dev": true - }, - "@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", - "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.6.tgz", - "integrity": "sha512-+1byPnimWdGcKFRS48zG73nxM08kamPFReUYvEmRXI3E8E4YhF4voMRDaGlfGD1UeRHEgs4NhQCE28KI8JVj1A==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "requires": { - "follow-redirects": "^1.10.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "boolean": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.4.tgz", - "integrity": "sha512-3hx0kwU3uzG6ReQ3pnaFQPSktpBw6RHN3/ivDKEuU8g1XSfafowyvDnadjv1xp8IZqhtSukxlwv9bF6FhX8m0w==", - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "dev": true, - "requires": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-spinners": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", - "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "optional": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "core-js": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.17.1.tgz", - "integrity": "sha512-C8i/FNpVN2Ti89QIJcFn9ZQmnM+HaAQr2OpE+ja3TRM9Q34FigsGlAVuwPGkIgydSVClo/1l1D1grP8LVt9IYA==", - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "optional": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "optional": true - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "electron": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-14.0.0.tgz", - "integrity": "sha512-O6EI7L1BPIrTpEIFefjjmdbmSn9LtE4mmrv4dfpV4Mqaa8uKuNYQogwZPEvSwaBexb69eb1LQ25n+f+kBcjiRQ==", - "dev": true, - "requires": { - "@electron/get": "^1.0.1", - "@types/node": "^14.6.2", - "extract-zip": "^1.0.3" - } - }, - "electron-rebuild": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-3.2.3.tgz", - "integrity": "sha512-9oxNmKlDCaf651c+yJWCDIBpF6A9aY+wQtasLEeR5AsPYPuOKEX6xHnC2+WgCLOC94JEpCZznecyC84fbwZq4A==", - "dev": true, - "requires": { - "@malept/cross-spawn-promise": "^2.0.0", - "colors": "^1.3.3", - "debug": "^4.1.1", - "detect-libc": "^1.0.3", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "lzma-native": "^8.0.1", - "node-abi": "^2.19.2", - "node-api-version": "^0.1.4", - "node-gyp": "^8.1.0", - "ora": "^5.1.0", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "dependencies": { - "@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "requires": { - "defer-to-connect": "^2.0.0" - } - }, - "cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - } - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "requires": { - "mimic-response": "^3.1.0" - } - }, - "defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true - }, - "fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", - "dev": true, - "requires": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - } - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - }, - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true - }, - "responselike": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", - "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", - "dev": true, - "requires": { - "lowercase-keys": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "optional": true - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "optional": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "optional": true - }, - "extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "dev": true, - "requires": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", - "yauzl": "^2.10.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "follow-redirects": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", - "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "global-agent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.2.0.tgz", - "integrity": "sha512-+20KpaW6DDLqhG7JDiJpD1JvNvb8ts+TNl7BPOYcURqCrXqnN1Vf+XVOrkKJAFPqfX+oEhsdzOj1hLWkBTdNJg==", - "dev": true, - "optional": true, - "requires": { - "boolean": "^3.0.1", - "core-js": "^3.6.5", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "optional": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "global-tunnel-ng": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", - "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", - "dev": true, - "optional": true, - "requires": { - "encodeurl": "^1.0.2", - "lodash": "^4.17.10", - "npm-conf": "^1.1.3", - "tunnel": "^0.0.6" - } - }, - "globalthis": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", - "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", - "dev": true, - "optional": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "optional": true - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true, - "optional": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "optional": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "lzma-native": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/lzma-native/-/lzma-native-8.0.1.tgz", - "integrity": "sha512-Ryr9X3yDVZhRYOxR8QhUBCNe6GdEfy9BvFDIFtUvEkocvSvnrYt9lRm6FR1z0eQn0QSMenrgrDIJRMgUf9zsKQ==", - "dev": true, - "requires": { - "node-addon-api": "^3.1.0", - "node-gyp-build": "^4.2.1", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "make-fetch-happen": { - "version": "8.0.14", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz", - "integrity": "sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==", - "dev": true, - "requires": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.0.5", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^5.0.0", - "ssri": "^8.0.0" - } - }, - "matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "optional": true, - "requires": { - "escape-string-regexp": "^4.0.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "dev": true, - "requires": { - "encoding": "^0.1.12", - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", - "dev": true, - "requires": { - "semver": "^5.4.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "node-addon-api": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", - "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==" - }, - "node-api-version": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.1.4.tgz", - "integrity": "sha512-KGXihXdUChwJAOHO53bv9/vXcLmdUsZ6jIptbvYvkpKfth+r7jw44JkVxQFA3kX5nQjzjmGu1uAu/xNNLNlI5g==", - "dev": true, - "requires": { - "semver": "^7.3.5" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "node-gyp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.2.0.tgz", - "integrity": "sha512-KG8SdcoAnw2d6augGwl1kOayALUrXW/P2uOAm2J2+nmW/HjZo7y+8TDg7LejxbekOOSv3kzhq+NSUYkIDAX8eA==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^8.0.14", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", - "dev": true - }, - "nodemailer": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.0.tgz", - "integrity": "sha512-ikSMDU1nZqpo2WUPE0wTTw/NGGImTkwpJKDIFPZT+YvvR9Sj+ze5wzu95JHkBMglQLoG2ITxU21WukCC/XsFkg==" - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true - }, - "npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "dev": true, - "optional": true, - "requires": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "optional": true - }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true, - "optional": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "optional": true, - "requires": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "optional": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true, - "optional": true - }, - "serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "optional": true, - "requires": { - "type-fest": "^0.13.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true - }, - "socks": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", - "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", - "dev": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" - } - }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true, - "optional": true - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "requires": { - "debug": "^4.1.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "optional": true - }, - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "optional": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "requires": { - "prepend-http": "^2.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yargs": { - "version": "17.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz", - "integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - } -} diff --git a/package.json b/package.json index d319d6b..2b2f114 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "ocoge", "version": "0.1.3", "description": "\"大岩産 Code Generator\" は、Google Blockly ライブラリを使用した、Raspberry Pi 上で動作するブロックプログラム開発・実行環境です。", - "main": "index.js", + "main": "main.js", "scripts": { "start": "electron .", "rebuild": "electron-rebuild" @@ -19,14 +19,15 @@ }, "homepage": "https://github.com/ocogeclub/ocoge#readme", "devDependencies": { - "electron": "^14.0.0", - "electron-rebuild": "^3.2.3" + "electron": "15.0.0", + "electron-rebuild": "3.2.3" }, "dependencies": { - "@electron/remote": "^1.2.1", "@ocogeclub/bme280": "file:local_modules/@ocogeclub/bme280", "@ocogeclub/lgpio": "file:local_modules/@ocogeclub/lgpio", "axios": "^0.21.1", - "nodemailer": "^6.6.0" + "nodemailer": "^6.6.0", + "@tensorflow/tfjs-node": "^3.9.0", + "@vladmandic/face-api": "^1.5.3" } -} +} \ No newline at end of file diff --git a/preload.js b/preload.js new file mode 100644 index 0000000..ea5a702 --- /dev/null +++ b/preload.js @@ -0,0 +1,19 @@ +const electron = require("electron") +const path = require('path') + +electron.contextBridge.exposeInMainWorld( + "ocogeapi", + { + // Electron固有:index.htmlから直接