-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathbuild.js
117 lines (117 loc) · 52.7 KB
/
build.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
(()=>{"use strict";var __webpack_modules__={121:function(__unused_webpack_module,exports,__webpack_require__){var _a,_b,_c,__createBinding=this&&this.__createBinding||(Object.create?function(o,m,k,k2){void 0===k2&&(k2=k);var desc=Object.getOwnPropertyDescriptor(m,k);desc&&!("get"in desc?!m.__esModule:desc.writable||desc.configurable)||(desc={enumerable:!0,get:function(){return m[k]}}),Object.defineProperty(o,k2,desc)}:function(o,m,k,k2){void 0===k2&&(k2=k),o[k2]=m[k]
}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(o,v){Object.defineProperty(o,"default",{enumerable:!0,value:v})}:function(o,v){o.default=v}),__importStar=this&&this.__importStar||function(mod){if(mod&&mod.__esModule)return mod;var result={};if(null!=mod)for(var k in mod)"default"!==k&&Object.prototype.hasOwnProperty.call(mod,k)&&__createBinding(result,mod,k);return __setModuleDefault(result,mod),result},__importDefault=this&&this.__importDefault||function(mod){
return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0})
;const chalk_1=__importDefault(__webpack_require__(895)),child_process_1=__webpack_require__(317),fs=__importStar(__webpack_require__(896)),os=__importStar(__webpack_require__(857)),readline=__importStar(__webpack_require__(785)),util_1=__webpack_require__(714),path=__importStar(__webpack_require__(928)),rpi_pin_conversions_1=__webpack_require__(283),process_util_1=__webpack_require__(990),util_2=__webpack_require__(23),fs_1=__webpack_require__(896),awcs_util_1=__webpack_require__(677),enoughRam=os.totalmem()/1073741824>1.5
;let copyfiles=__webpack_require__(980);copyfiles.default&&(copyfiles=copyfiles.default),readline.emitKeypressEvents(process.stdin),process.stdin.setRawMode(!0);const isWindows="win32"===process.platform
;let doAdmin,spinStep=0,lastSpin=0,doUpdateUpgrade=!0,doNpmI=!0,npmInitDone=!1,doAcu=!1,clearAcu=!1,clearFirefox=!1,doDht=!1,clearDht=!1,doFirefox=null,doFullscreen=null,doKiosk=null,clearFullscreen=!1,clearKiosk=!1,doStdDeploy=!1,doDedicated=!1,doLaunch=!1,doReboot=!1,hasFirefox=!1,noStop=!1,prod=!1,viaBash=!1,interactive=!1,treatAsRaspberryPi=process.argv.includes("--tarp"),isRaspberryPi=!1,isRaspberryPi5OrLater=!1,settingsOnly=!1,nodePath="",usingNvm=!1,spin=()=>{const now=(0,util_1.processMillis)()
;lastSpin<now-100&&(lastSpin=now,write(backspace+"|/-\\".charAt(spinStep)),spinStep=(spinStep+1)%4)};const chalk=new chalk_1.default.Instance;chalk.mediumGray=chalk.hex("#808080"),chalk.paleBlue=chalk.hex("#66CCFF"),chalk.paleYellow=chalk.hex("#FFFFAA");let backspace="\b",sol="[1G",trailingSpace=" ",totalSteps=3,currentStep=0;const settings={AWC_ALLOW_ADMIN:"false",AWC_ALLOW_CORS:"true",AWC_KIOSK_MODE:"kiosk",AWC_LOG_CACHE_ACTIVITY:"false",AWC_NTP_SERVERS:"",AWC_PORT:"8080",
AWC_PREFERRED_WS:"wunderground",AWC_USE_FIREFOX:"false",AWC_WIRED_TH_GPIO:"17",AWC_WIRELESS_TH_GPIO:"27"},userHome=(0,process_util_1.getUserHome)(),sudoUser=(0,process_util_1.getSudoUser)(),user=process.env.SUDO_USER||process.env.USER||"pi";let uid;const cpuPath2="/sys/firmware/devicetree/base/model",settingsPath="/etc/default/weatherService",rpiSetupStuff=path.join(__dirname,"raspberry_pi_setup"),serviceSrc=rpiSetupStuff+"/weatherService",fontSrc=rpiSetupStuff+"/fonts/",fontDst="/usr/local/share/fonts/"
;let chromium="chromium",autostartDst=".config/lxsession/LXDE";if("linux"===process.platform)try{if(fs.existsSync("/proc/cpuinfo")){const lines=(0,util_1.asLines)(fs.readFileSync("/proc/cpuinfo").toString());fs.existsSync(cpuPath2)&&lines.push(...(0,util_1.asLines)(fs.readFileSync(cpuPath2).toString()));for(const line of lines){if(!isRaspberryPi&&/\b(Raspberry Pi|BCM\d+)\b/i.test(line)&&(isRaspberryPi=treatAsRaspberryPi=!0,autostartDst+="-pi",chromium+="-browser",isRaspberryPi5OrLater))break
;if(!isRaspberryPi5OrLater&&(0,util_1.toInt)((/Model\s+:\s+Raspberry Pi (\d+)/.exec(line)||[])[1])>=5&&(isRaspberryPi5OrLater=!0,isRaspberryPi))break}}}catch(err){console.error(chalk.redBright("Raspberry Pi check failed"))}!isRaspberryPi&&!treatAsRaspberryPi||process.env.DISPLAY||(process.env.DISPLAY=":0.0");const launchChromium=chromium+" http://localhost:8080/",autostartEntryPattern=new RegExp("^\\/.*\\b"+(0,
awcs_util_1.escapeForRegex)("autostart_extra.sh")+"\\b"),oldAutostartEntryPattern=new RegExp(`^@(${chromium}|firefox)\\b.*\\bhttp:\\/\\/localhost:\\d+\\/$`);/\b(ts-)?node\b/.test(null!==(_a=process.argv[0])&&void 0!==_a?_a:"")&&process.argv.splice(0,1),/\bbuild(\.[jt]s)?\b/.test(null!==(_b=process.argv[0])&&void 0!==_b?_b:"")&&process.argv.splice(0,1),0===process.argv.length&&treatAsRaspberryPi&&!viaBash&&(console.warn(chalk.yellow("Warning: no build options specified.")),
console.warn(chalk.yellow("This could be OK, or this could mean you forgot the leading ")+chalk.white("--")+chalk.yellow(" before your options.")));const onlyOnRaspberryPi=[],onlyDedicated=[];let helpMsg,getPathArg=!1;if(process.argv.forEach((arg=>{if(getPathArg){const path=process.env.PATH;return nodePath=arg.trim().replace(/^"|"$/g,""),process.env.NODE_PATH=nodePath,process.env.PATH=nodePath+(path?":"+path:""),getPathArg=!1,void(usingNvm=nodePath.includes("/.nvm/"))}switch(arg){case"--":case"--tarp":
break;case"--acu":doAcu=!0;break;case"--acu-":doAcu=!1,clearAcu=!0;break;case"--admin":doAdmin=!0;break;case"--admin-":doAdmin=!1;break;case"--bash":viaBash=!0,delete process.env.SHLVL;break;case"--ddev":doDedicated=doStdDeploy=!0,onlyOnRaspberryPi.push(arg);break;case"--dht":doDht=!0,onlyOnRaspberryPi.push(arg);break;case"--dht-":doDht=!1,clearDht=!0;break;case"--firefox":doFirefox=!0,clearFirefox=!1;break;case"--firefox-":doFirefox=!1,clearFirefox=!0;break;case"--fullscreen":doFullscreen=!0,doKiosk=!1,
clearFullscreen=!1;break;case"--fullscreen-":doFullscreen=!1,clearFullscreen=!0;break;case"-i":interactive=doStdDeploy=doDedicated=!0,onlyOnRaspberryPi.push(arg),delete process.env.SHLVL;break;case"-is":interactive=settingsOnly=noStop=!0,onlyOnRaspberryPi.push(arg),delete process.env.SHLVL;break;case"--kiosk":doKiosk=!0,doFullscreen=!1,clearKiosk=!1;break;case"--kiosk-":doKiosk=!1,clearKiosk=!0;break;case"--launch":doLaunch=!0,onlyOnRaspberryPi.push(arg),onlyDedicated.push(arg);break;case"--nostop":
noStop=!0;break;case"-p":prod=!0;break;case"--path":getPathArg=!0;break;case"--pt":spin=void 0,chalk.level=0,backspace="",sol="",trailingSpace=" ";break;case"--reboot":doReboot=!0,doLaunch=!1,onlyOnRaspberryPi.push(arg),onlyDedicated.push(arg);break;case"--sd":doStdDeploy=!0,onlyOnRaspberryPi.push(arg);break;case"--skip-upgrade":doUpdateUpgrade=!1,onlyOnRaspberryPi.push(arg);break;case"--skip-npm-i":doNpmI=!1;break;default:
helpMsg="Usage: sudo ./build.sh [--acu] [--admin] [--ddev] [--dht] [--firefox]\n [--fullscreen] [--gps] [--help] [-i] [--launch]\n [--kiosk] [-p] [--pt] [--reboot] [--sd]\n [--skip-upgrade] [--tarp]\n\nThe options --acu, --admin, --dht, --firefox, --fullscreen, and --kiosk\ncan be followed by an extra dash (e.g. --acu-) to clear a previously\nenabled option.",
viaBash||(helpMsg=helpMsg.replace("sudo ./build.sh","npm run build").replace(/\n {2}/g,"\n")),"--help"!==arg&&"-h"!==arg&&console.error('Unrecognized option "'+chalk.redBright(arg)+'"'),console.log(helpMsg),process.exit(1)}})),noStop&&(doReboot=doLaunch=!1),!treatAsRaspberryPi&&onlyOnRaspberryPi.length>0&&(onlyOnRaspberryPi.forEach((opt=>console.error(chalk.redBright(opt)+" option is only valid on Raspberry Pi"))),process.exit(1)),
!doDedicated&&onlyDedicated.length>0&&(onlyDedicated.forEach((opt=>console.error(chalk.redBright(opt)+" option is only valid when used with the --ddev or -i options"))),process.exit(1)),treatAsRaspberryPi)try{if(fs.existsSync(settingsPath)){const lines=(0,util_1.asLines)(fs.readFileSync(settingsPath).toString()),oldSettings={};lines.forEach((line=>{const $=/^\s*(\w+)\s*=\s*(\S+)/.exec(line);$&&(oldSettings[$[1]]=settings[$[1]]=$[2])})),void 0===doAdmin?doAdmin=(0,
util_1.toBoolean)(oldSettings.AWC_ALLOW_ADMIN):settings.AWC_ALLOW_ADMIN=null==doAdmin?void 0:doAdmin.toString(),!oldSettings.AWC_WIRED_TH_GPIO&&(0,util_1.toBoolean)(oldSettings.AWC_HAS_INDOOR_SENSOR)&&(oldSettings.AWC_WIRED_TH_GPIO=settings.AWC_WIRED_TH_GPIO=settings.AWC_TH_SENSOR_GPIO||"4"),!clearDht&&oldSettings.AWC_WIRED_TH_GPIO&&(doDht=!0),!settings.AWC_WIRELESS_TH_GPIO&&oldSettings.AWC_WIRELESS_TEMP&&(oldSettings.AWC_WIRELESS_TH_GPIO=settings.AWC_WIRELESS_TH_GPIO=settings.AWC_WIRELESS_TEMP),
!clearAcu&&oldSettings.AWC_WIRELESS_TH_GPIO&&(doAcu=!0),settings.AWC_NTP_SERVERS||("pool.ntp.org"===oldSettings.AWC_NTP_SERVER?settings.AWC_NTP_SERVERS="":oldSettings.AWC_NTP_SERVER&&(settings.AWC_NTP_SERVERS=oldSettings.AWC_NTP_SERVER)),delete settings.AWC_HAS_INDOOR_SENSOR,delete settings.AWC_TH_SENSOR_GPIO,delete settings.AWC_WIRELESS_TEMP,delete settings.AWC_NTP_SERVER
;const oldKiosk=/^(fa|0)/i.test(oldSettings.AWC_KIOSK_MODE)?"n":null===(_c=oldSettings.AWC_KIOSK_MODE)||void 0===_c?void 0:_c.toLowerCase().charAt(0);doKiosk=!clearKiosk&&(null!=doKiosk?doKiosk:!oldKiosk||/[kt]/.test(oldKiosk)),doFullscreen=!clearFullscreen&&(null!=doFullscreen?doFullscreen:"f"===oldKiosk),settings.AWC_KIOSK_MODE=doKiosk?"kiosk":doFullscreen?"full-screen":"no",clearFirefox?doFirefox=!1:null==doFirefox&&(doFirefox=(0,util_1.toBoolean)(oldSettings.AWC_USE_FIREFOX)),
doFirefox&&"full-screen"===settings.AWC_KIOSK_MODE&&(settings.AWC_KIOSK_MODE="kiosk",doKiosk=!0,doFullscreen=!1),settings.AWC_USE_FIREFOX=doFirefox.toString()}}catch(err){console.warn(chalk.yellow("Existing settings check failed. Defaults will be used."))}async function readUserInput(){return new Promise((resolve=>{let buffer="",length=0;const clearLine=()=>write("\b \b".repeat(length)),callback=(ch,key)=>{""===ch?(write("^C\n"),process.exit(130)):""===ch?(clearLine(),
length=0):"enter"===key.name||"return"===key.name?(write("\n"),process.stdin.off("keypress",callback),resolve(buffer.substr(0,length).trim())):"backspace"===key.name||"left"===key.name?length>0&&(write("\b \b"),--length):"delete"===key.name?length>0&&(write("\b \b"),buffer=buffer.substr(0,--length)+buffer.substr(length+1)):"up"===key.name?(clearLine(),write("\n"),process.stdin.off("keypress",callback),
resolve("")):"right"===key.name?length<buffer.length&&write(buffer.charAt(length++)):null!=ch&&ch>=" "&&!key.ctrl&&!key.meta&&(write(ch),buffer=buffer.substr(0,length)+ch+buffer.substr(length++))};process.stdin.on("keypress",callback)}))}function write(s){process.stdout.write(s)}function stepDone(){console.log(backspace+chalk.green("✔"))}async function isInstalled(command){var _a;return"libgpiod-dev"===command?(0,fs_1.existsSync)("/usr/include/gpiod.h"):!!(null===(_a=await(0,
process_util_1.monitorProcess)((0,process_util_1.spawn)("command",["-v",command],{shell:!0}),null,process_util_1.ErrorMode.ANY_ERROR))||void 0===_a?void 0:_a.trim())}async function install(cmdPkg,viaNpm=!1,realOnly=!1,quiet=!1){const packageArgs=[cmdPkg];let name=cmdPkg;return quiet||showStep(),realOnly&&!isRaspberryPi?(console.log(`${chalk.bold(cmdPkg)} won't be installed (not real Raspberry Pi)`+trailingSpace+backspace+chalk.green("✔")),!1):("gpiod"===cmdPkg&&(name="gpioinfo"),
await isInstalled(name)?(quiet?stepDone():console.log(`${chalk.bold(cmdPkg)} already installed`+trailingSpace+backspace+chalk.green("✔")),!1):(quiet||write(`Installing ${chalk.bold(cmdPkg)}`+trailingSpace),viaNpm?await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("npm",["install","-g",...packageArgs]),spin,process_util_1.ErrorMode.ANY_ERROR):await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("apt-get",["install","-y",...packageArgs]),spin,process_util_1.ErrorMode.ANY_ERROR),
stepDone(),!0))}function getWebpackSummary(s){const lines=(0,util_1.asLines)(s),summary=[];for(let line of lines)/(^(hash|version|time|built at):)|by path assets\/ |runtime modules|javascript modules|compiled successfully in/i.test(line)&&(line=line.trim(),summary.push(line.substr(0,72)+(line.length>72?"...":"")));return" "+summary.join("\n ")}var RepoStatus;async function getRepoStatus(){const lines=(0,util_1.asLines)((await(0,process_util_1.monitorProcess)((0,
process_util_1.spawn)("git",["status","--porcelain","-b"]))).trim());let status=RepoStatus.CLEAN;lines.length>0&&lines.splice(0,1);for(const line of lines){if(!/\bpackage-lock.json$/.test(line)){status=RepoStatus.DIRTY;break}status=RepoStatus.PACKAGE_LOCK_CHANGES_ONLY}return status}function showStep(){write(`Step ${++currentStep} of ${totalSteps}: `)}function chalkUp(s,currentStyle=s=>s){var _a;const closed=/(.*?)(\[([a-z]+)])(.*?)(\[\/\3])(.*)/.exec(s),open=/(.*?)(\[([a-z]+)])(.*)/.exec(s)
;if(!closed&&!open)return s;let $;$=closed&&open?open[1].length<closed[1].length?open:closed:null!=closed?closed:open;let style,chalked=$[4],end=null!==(_a=$[6])&&void 0!==_a?_a:"";switch($[5]||(chalked+=end,end=""),$[3]){case"pb":style=chalk.paleBlue;break;case"w":style=chalk.whiteBright}return $[1]+chalkUp(style(chalked),style)+currentStyle(chalkUp(end))}!isRaspberryPi&&doAcu&&console.warn(chalk.yellow("Warning: this setup will only generate fake wireless sensor data")),function(RepoStatus){
RepoStatus[RepoStatus.CLEAN=0]="CLEAN",RepoStatus[RepoStatus.PACKAGE_LOCK_CHANGES_ONLY=1]="PACKAGE_LOCK_CHANGES_ONLY",RepoStatus[RepoStatus.DIRTY=2]="DIRTY"}(RepoStatus||(RepoStatus={}));const DOMAIN_PATTERN=/^(((?!-))(xn--|_)?[-a-z\d]{0,61}[a-z\d]\.)*(xn--)?([a-z\d][-a-z\d]{0,60}|[-a-z\d]{1,30}\.[a-z]{2,})(:\d{1,5})?$/i;function yesOrNo(s,assign){return/^[yn]/i.test(s)?(assign(/^y/i.test(s)),!0):(console.log(chalk.redBright("Response must be (y)es or (n)o")),!1)}function firefoxValidate(s){
return/^[cf]/i.test(s)?(doFirefox=/^f/i.test(s),doFirefox.toString()):(console.log(chalk.redBright("Response must be (C)hrome or (F)irefox")),!1)}function kioskValidate(s){return/^[kfn]/i.test(s)?/^k/i.test(s)?(doKiosk=!0,doFullscreen=!1,"kiosk"):/^f/i.test(s)?(doKiosk=!1,doFullscreen=!0,"full-screen"):(doKiosk=!1,doFullscreen=!1,"no"):(console.log(chalk.redBright("Response must be (k)iosk, (f)ullscreen, or (n)either")),!1)}function pinValidate(s){return!((0,
rpi_pin_conversions_1.convertPinToGpio)(s)<0)||(console.log(chalk.redBright(s+" is not a valid pin number")),!1)}"darksky"===process.env.AWC_PREFERRED_WS&&(process.env.AWC_PREFERRED_WS="wunderground");const finalAction=doReboot?"R":doLaunch?"L":"#",finalOptions="(l/r/n)".replace(finalAction.toLowerCase(),finalAction);let questions=[{prompt:"Perform initial update/upgrade?",ask:!0,yn:!0,deflt:doUpdateUpgrade?"Y":"N",validate:function(s){return yesOrNo(s,(isYes=>doUpdateUpgrade=isYes))}},{
prompt:"Perform npm install? (N option for debug only)",ask:!0,yn:!0,deflt:doNpmI?"Y":"N",validate:function(s){return yesOrNo(s,(isYes=>doNpmI=isYes))}},{name:"AWC_PORT",prompt:"HTTP server port.",ask:!0,validate:function(s){const port=Number(s);return!(isNaN(port)||port<1||port>65535)||(console.log(chalk.redBright("Port must be a number from 1 to 65535")),!1)}},{prompt:"Allow user to reboot, shutdown, update, etc.?",ask:!0,yn:!0,deflt:doAdmin?"Y":"N",validate:function(s){
return yesOrNo(s,(isYes=>settings.AWC_ALLOW_ADMIN=isYes?"true":"false"))}},{name:"AWC_NTP_SERVERS",prompt:"time servers (comma-separated domains, blank for defaults)",ask:!0,validate:function(s){const domains=s.split(",").map((d=>d.trim()));return""===s.trim()||domains.length>0&&domains.findIndex((d=>!DOMAIN_PATTERN.test(d)))<0||(console.log(chalk.redBright("NTP servers must be a valid domain names (with optional port numbers)")),!1)}},{name:"AWC_GOOGLE_API_KEY",
prompt:"Optional Google geocoding API key (for city names from\n GPS coordinates)."+(settings.AWC_GOOGLE_API_KEY?"\n Enter - (dash) to remove old API key":""),ask:!0},{name:"AWC_PREFERRED_WS",prompt:"preferred weather service, (w)underground, weather(b)it,\n or (v)isual crossing).",ask:!0,validate:function(s){
return/^w[-b]*$/i.test(s)?"wunderground":/b/i.test(s)?"weatherbit":/^v/i.test(s)?"visual_x":(console.log(chalk.redBright("Weather service must be either (w)underground, weather(b)it, or (v)isual crossing")),!1)},after:function(s){/^w[-b]*$/i.test(s)?(console.log(chalk.paleBlue(" Weather Underground chosen, but Weatherbit.io or Visual Crossing can be used")),
console.log(chalk.paleBlue(" as fallback weather services."))):/b/i.test(s)?(console.log(chalk.paleBlue(" Weatherbit.io chosen, but Weather Underground will be used")),console.log(chalk.paleBlue(" as a fallback weather service."))):/^v/i.test(s)&&(console.log(chalk.paleBlue(" Visual Crossing chosen, but Weather Underground will be used")),console.log(chalk.paleBlue(" as a fallback weather service.")))}},{name:"AWC_WEATHERBIT_API_KEY",
prompt:"Optional Weatherbit.io (via RapidAPI) key, for\n weather and geocoding."+(settings.AWC_WEATHERBIT_API_KEY?"\n Enter - (dash) to remove old API key":""),ask:!0},{name:"AWC_VISUAL_CROSSING_API_KEY",prompt:"Optional Visual Crossing weather API key."+(settings.AWC_VISUAL_CROSSING_API_KEY?"\n Enter - (dash) to remove old API key":""),ask:!0},{prompt:"Use wired DHT temperature/humidity sensor?",ask:!0,yn:!0,deflt:doDht?"Y":"N",validate:function(s){return yesOrNo(s,(isYes=>doDht=isYes))}},{
name:"AWC_WIRED_TH_GPIO",prompt:"GPIO pin number for wired temp/humidity sensor",ask:()=>doDht,validate:pinValidate},{prompt:"Use wireless temperature/humidity sensors?",ask:!0,yn:!0,deflt:doAcu?"Y":"N",validate:function(s){return yesOrNo(s,(isYes=>doAcu=isYes))}},{name:"AWC_WIRELESS_TH_GPIO",prompt:"GPIO pin number for wireless temp/humidity sensors",ask:()=>doAcu,validate:pinValidate},{prompt:`When finished, (l)aunch A/W clock, (r)eboot, or (n)o action ${finalOptions}?`,ask:!0,deflt:finalAction,
validate:function(s){let $;return($=/^([lrn])/i.exec(s.toLowerCase()))?("l"===$[1]?(doLaunch=!0,doReboot=!1):"r"===$[1]?(doLaunch=!1,doReboot=!0):treatAsRaspberryPi&&(doLaunch=doReboot=!1),!0):(console.log(chalk.redBright("Response must be (l)aunch, (r)eboot, or (n)o action")),!1)}}];async function doServerBuild(){!doNpmI&&fs.existsSync("server/node_modules")&&fs.existsSync("server/package-lock.json")||(showStep(),write("Updating server"+trailingSpace),await(0,process_util_1.monitorProcess)((0,
process_util_1.spawn)("npm",uid,["i","--no-save"],{cwd:path.join(__dirname,"server")}),spin),stepDone()),showStep(),write("Building server"+trailingSpace),fs.existsSync("server/dist")&&await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("rm",uid,["-Rf","server/dist"]),spin);const opts={shell:!0,cwd:path.join(__dirname,"server"),env:process.env},output=getWebpackSummary(await(0,process_util_1.monitorProcess)((0,
process_util_1.spawn)("npm",uid,["run",isWindows?"build-win":"build"+(enoughRam?"":":tiny")],opts),spin));if(stepDone(),(null==output?void 0:output.trim())&&console.log(chalk.mediumGray(output)),doAcu||doDht){showStep();const args=["i","-P","rpi-acu-rite-temperature@3","node-dht-sensor"];isRaspberryPi5OrLater&&args.push("--use_libgpiod=true"),doAcu&&doDht?write("Adding wireless and wired temp/humidity sensor support"+trailingSpace):doAcu?(args.splice(3,1),
write("Adding Acu-Rite wireless temperature/humidity sensor support"+trailingSpace)):(args.splice(2,1),write("Adding DHT wired temperature/humidity sensor support"+trailingSpace)),await async function(){if(!npmInitDone){const file=path.join(__dirname,"server","dist","package.json"),packageJson={name:"aw-clock-server",version:"0.0.0",description:"AW-Clock Server",main:"app.js",license:"MIT",dependencies:{}};fs.writeFileSync(file,JSON.stringify(packageJson,null,2)),await(0,process_util_1.monitorProcess)((0,
process_util_1.spawn)("chown",[user,file]),spin,process_util_1.ErrorMode.ANY_ERROR),npmInitDone=!0}}(),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("npm",uid,args,{cwd:path.join(__dirname,"server","dist")}),spin),stepDone()}}function writeSettings(){const settingsText=`# If you edit AWC_PORT below, be sure to update\n# ${userHome}/${autostartDst}/autostart_extra.sh\n# accordingly.\n`+Object.keys(settings).sort().map((key=>key+"="+settings[key])).join("\n")+"\n"
;fs.writeFileSync(settingsPath,settingsText)}(async()=>{var _a;try{hasFirefox=await isInstalled("firefox"),uid=Number((await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("id",["-u",user]))).trim()||"1000");const nodeVersionStr=(await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("node",uid,["--version"]))).trim(),nodeVersion=(0,util_1.toNumber)((null!==(_a=/v(\d+)/.exec(nodeVersionStr))&&void 0!==_a?_a:[])[1])
;if(isRaspberryPi&&nodeVersion<10&&(console.error(chalk.redBright(`Node.js version 10 or later required. Version ${nodeVersionStr} found.`)),process.exit(1)),treatAsRaspberryPi&&!isRaspberryPi){const isDebian=/^Linux\b.+\bDebian\b/i.test(await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("uname",["-a"]))),isLxde=await isInstalled("lxpanel");isDebian&&isLxde||(console.error(chalk.redBright("--tarp option (Treat As Raspberry Pi) only available for Linux Debian with LXDE")),process.exit(1))}
if(isRaspberryPi&&await async function(){console.log(chalk.cyan("- GPS test -"));const hasGpsTools=await isInstalled("gpsd")&&await isInstalled("gpspipe"),hasNtpTools=await isInstalled("ntpd")&&await isInstalled("ntpq"),hasPpsTools=await isInstalled("ppstest");let gpsLocationIsWorking=!1,gpsTimeIsWorking=!1;if(hasGpsTools){const gpsInfo=await new Promise(((resolve,reject)=>{const proc=(0,process_util_1.spawn)("gpspipe",["-w","-n","12"]);let finished=!1;(0,
process_util_1.monitorProcessLines)(proc,null,process_util_1.ErrorMode.NO_ERRORS).then((lines=>{finished=!0,resolve(lines)})).catch((err=>{finished=!0,reject(err)})),setTimeout((()=>{finished||(proc.kill(),console.warn(chalk.yellow("Warning: gpspipe timed out.")),resolve([]))}),1e4)}));for(const line of gpsInfo)try{const obj=JSON.parse(line);if((0,util_1.isObject)(obj)&&(0,util_1.isNumber)(obj.lat)&&(0,util_1.isNumber)(obj.lon)){gpsLocationIsWorking=!0;break}}catch(_a){}}if(hasNtpTools){
const ntpInfo=await new Promise(((resolve,reject)=>{const proc=(0,process_util_1.spawn)("ntpq",["-p"]);let finished=!1;(0,process_util_1.monitorProcessLines)(proc,null,process_util_1.ErrorMode.NO_ERRORS).then((lines=>{finished=!0,resolve(lines)})).catch((err=>{finished=!0,reject(err)})),setTimeout((()=>{finished||(proc.kill(),console.warn(chalk.yellow("Warning: ntpq timed out.")),resolve([]))}),1e4)}));for(const line of ntpInfo)if(/^\*SHM\b.+\.PPS\.\s+0\s+l\s+.+?\s[-+]?[.\d]+\s+[.\d]+\s*$/.test(line)){
gpsTimeIsWorking=!0;break}}if(gpsLocationIsWorking&&gpsTimeIsWorking)console.log("GPS time and location services found "+chalk.green("✔"));else{const hasChrony=await isInstalled("chrony");console.log(chalk.yellow("GPS time and/or location services not found")),console.log(chalk.yellow("The following updates/changes are suggested if GPS support is desired:")),hasChrony&&console.log(chalkUp(" [pb]• Remove [w]chrony[/w] package to avoid conflict with ntpd.")),
hasGpsTools?console.log(chalkUp(" [pb]• Check [w]gpsd[/w] configuration")):console.log(chalkUp(" [pb]• Install [w]gpsd[/w] and [w]gpspipe[/w]")),hasNtpTools?console.log(chalkUp(" [pb]• Check [w]ntpd[/w] configuration")):console.log(chalkUp(" [pb]• Install [w]ntpd[/w] and [w]ntpq[/w]")),hasPpsTools||console.log(chalkUp(" [pb]• Install [w]pps-tools[/w]"))}}(),interactive&&await async function(){let altKioskQuestion;doDedicated&&(hasFirefox&&questions.splice(questions.length-1,0,{
prompt:"Launch browser with (C)hrome or (F)irefox?",ask:!0,opts:"cf",deflt:()=>doFirefox?"F":"C",validate:firefoxValidate,name:"AWC_USE_FIREFOX"}),questions.splice(questions.length-1,0,{prompt:"Launch browser in (k)iosk mode, (f)ull-screen, or (n)either?",ask:!0,opts:"kfn",deflt:()=>doKiosk?"K":doFullscreen?"F":"N",validate:kioskValidate,name:"AWC_KIOSK_MODE"}),altKioskQuestion={prompt:"Launch browser in kiosk mode?",ask:!0,yn:!0,deflt:()=>doKiosk||doFullscreen?"Y":"N",name:"AWC_KIOSK_MODE"}),
noStop&&(questions=questions.slice(0,-1)),console.log(chalk.cyan(sol+"- Configuration -"));for(let i=0;i<questions.length;++i){let q=questions[i];"AWC_KIOSK_MODE"===q.name&&doFirefox&&(q=altKioskQuestion);const deflt=(0,util_1.isFunction)(q.deflt)?q.deflt():q.deflt;if(!((0,util_1.isFunction)(q.ask)?q.ask():q.ask))continue;!q.name||q.opts||q.yn?(write(q.prompt),
q.yn?write("Y"===deflt?" (Y/n)":" (y/N)"):q.opts&&deflt&&write(" ("+q.opts.split("").map((c=>c===deflt.toLowerCase()?c.toUpperCase():c)).join("/")+")"),write(": ")):write(chalk.bold(q.name)+" - "+q.prompt+"\n "+(settings[q.name]?"(default: "+chalk.paleYellow(settings[q.name])+")":"")+": ");let response=await readUserInput();if(!response&&q.yn&&(response=deflt),""!==response){if(response){const validation=!q.validate||q.validate(response);if((0,
util_1.isString)(validation))settings[q.name]=validation;else{if(!validation){--i;continue}q.name&&("-"===response?delete settings[q.name]:q.yn?settings[q.name]=(0,util_1.toBoolean)(response).toString():settings[q.name]=response)}}else response||"#"!==q.deflt||(--i,console.log(chalk.redBright("Response required")));q.after&&q.after(settings[q.name])}else i=Math.max(i-2,-1)}}(),process.stdin.setRawMode(!1),settingsOnly||(totalSteps+=noStop?0:1,
totalSteps+=!doNpmI&&fs.existsSync("node_modules")&&fs.existsSync("package-lock.json")?0:1,totalSteps+=!doNpmI&&fs.existsSync("server/node_modules")&&fs.existsSync("server/package-lock.json")?0:1,totalSteps+=doAcu||doDht?1:0,totalSteps+=doStdDeploy||doDedicated?1:0,totalSteps+=doLaunch||doReboot?1:0),doDht||delete settings.AWC_WIRED_TH_GPIO,doAcu||delete settings.AWC_WIRELESS_TH_GPIO,doDedicated){if(totalSteps+=9+(doUpdateUpgrade?1:0),console.log(chalk.cyan(sol+"- Dedicated device setup -")),
doUpdateUpgrade&&(showStep(),write("Updating/upgrading packages (can take a long time!)"+trailingSpace),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("apt-get",["update","-y"]),spin,process_util_1.ErrorMode.NO_ERRORS),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("apt-get",["upgrade","-y"]),spin,process_util_1.ErrorMode.NO_ERRORS),stepDone()),!noStop){showStep(),write("Stopping weatherService if currently running"+trailingSpace);try{await(0,
process_util_1.monitorProcess)((0,process_util_1.spawn)("service",["weatherService","stop"]),spin,process_util_1.ErrorMode.ANY_ERROR)}catch(err){const msg=err.message||err.toString();/Interactive authentication required/i.test(msg)&&(console.log(backspace+trailingSpace),console.error(err),console.log("\npolkit is requiring interactive authentication to stop weatherService."),console.log('Please enter "sudo service weatherService stop" at the prompt below.'),
console.log("\nWhen that is done, restart this installation with either: "),console.log(" sudo ./build.sh --nostop -i (for interactive set-up)"),console.log(" sudo ./build.sh --nostop -ddev (for automated set-up)"),process.exit(1))}stepDone()}await install("gpiod",!1,!0),await install("libgpiod-dev",!1,!0),await install(chromium),await install("unclutter");for(let i=0;i<2;++i)try{await install("forever",!0,!1,i>0);break}catch(_b){i>0&&console.log(backspace+chalk.paleYellow("✘"))}
await async function(){showStep();const fontsToAdd=fs.readdirSync(fontSrc).filter((name=>/.\.ttf/i.test(name))).filter((font=>!fs.existsSync(fontDst+font)));if(fontsToAdd.length>0){write("Installing fonts"+trailingSpace);for(const font of fontsToAdd)await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("cp",[fontSrc+font,fontDst+font]),spin,process_util_1.ErrorMode.ANY_ERROR);await(0,process_util_1.monitorProcess)((0,
process_util_1.spawn)("fc-cache",["-f"]),spin,process_util_1.ErrorMode.ANY_ERROR)}else write("Fonts already installed"+trailingSpace);stepDone()}();try{await async function(uid){var _a;const screenSaverJustInstalled=await install("xscreensaver"),settingsFile=`${userHome}/.xscreensaver`;if(showStep(),write("Disabling screen saver"+trailingSpace),screenSaverJustInstalled||!fs.existsSync(settingsFile)){const procList=await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("ps",["-ax"]),spin)
;/\d\s+xscreensaver\b/.test(procList)||((0,process_util_1.spawn)("xscreensaver",[],{uid,detached:!0,env:process.env}),await(0,process_util_1.sleep)(500));const settingsProcess=(0,process_util_1.spawn)("xscreensaver-demo",[],{uid,env:process.env});await(0,process_util_1.sleep)(3e3,spin),settingsProcess.kill("SIGTERM"),await(0,process_util_1.sleep)(500,spin)}await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("sed",["-i","-r","'s/^(mode:\\s+)\\w+$/\\1off/'",settingsFile],{uid,shell:!0
}),spin,process_util_1.ErrorMode.ANY_ERROR);const procList=await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("ps",["-ax"]),spin),ssProcessNo=(null!==(_a=/^(\d+)\s+.*\d\s+xscreensaver\b/.exec(procList))&&void 0!==_a?_a:[])[1];ssProcessNo&&await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("kill",[ssProcessNo]),spin),(0,process_util_1.spawn)("xscreensaver",[],{uid,detached:!0}),stepDone()}(uid)}catch(_c){console.log(backspace+chalk.paleYellow("✘"))}}
if(settings.AWC_GIT_REPO_PATH=(await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("pwd"),spin,process_util_1.ErrorMode.NO_ERRORS)).trim()||settings.AWC_GIT_REPO_PATH,settings.AWC_GIT_REPO_PATH||delete settings.AWC_GIT_REPO_PATH,settingsOnly)writeSettings();else{console.log(chalk.cyan(sol+"- Building application -"));const repoStatus1=await getRepoStatus();await async function(){!doNpmI&&fs.existsSync("node_modules")&&fs.existsSync("package-lock.json")||(showStep(),
write("Updating client"+trailingSpace),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("npm",uid,["i","--no-save"]),spin),stepDone()),showStep(),write("Building client"+trailingSpace),fs.existsSync("dist")&&await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("rm",uid,["-Rf","dist"]),spin);const opts={shell:!0,env:process.env},args=["run","build:client"+(enoughRam?"":":tiny")];prod&&args.push("--","--env","mode=prod");const output=getWebpackSummary(await(0,
process_util_1.monitorProcess)((0,process_util_1.spawn)("npm",uid,args,opts),spin));stepDone(),(null==output?void 0:output.trim())&&console.log(chalk.mediumGray(output))}(),await doServerBuild();const repoStatus2=await getRepoStatus();viaBash&&repoStatus1===RepoStatus.CLEAN&&repoStatus2===RepoStatus.PACKAGE_LOCK_CHANGES_ONLY&&await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("git",["reset","--hard"])),showStep(),write("Copying server to top-level dist directory"+trailingSpace),await(0,
util_2.promisify)(copyfiles)(["server/dist/**/*","dist/"],{up:2}),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("chown",["-R",sudoUser,"dist"],{shell:!0}),spin,process_util_1.ErrorMode.ANY_ERROR),stepDone()}if(doStdDeploy&&(showStep(),write("Moving server to ~/weather directory"+trailingSpace),fs.existsSync(userHome+"/awc-alarm-tones")||fs.mkdirSync(userHome+"/awc-alarm-tones"),fs.existsSync(userHome+"/weather")?await(0,process_util_1.monitorProcess)((0,
process_util_1.spawn)("rm",["-Rf",userHome+"/weather/*"],{shell:!0}),spin,process_util_1.ErrorMode.ANY_ERROR):await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("mkdir",[userHome+"/weather"]),spin),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("mv",["dist/*",userHome+"/weather"],{shell:!0}),spin,process_util_1.ErrorMode.ANY_ERROR),usingNvm&&await(0,process_util_1.monitorProcess)((0,
process_util_1.spawn)("sed",["-i",`'1s#!/usr/bin/env node#!/usr/bin/env ${nodePath}/node#'`,userHome+"/weather/app.js"],{shell:!0}),spin,process_util_1.ErrorMode.ANY_ERROR),stepDone()),doDedicated&&(console.log(chalk.cyan(sol+"- Dedicated device service deployment -")),await async function(){let autostartDir=path.join(userHome,autostartDst);const wayfireIniPath=path.join(userHome,".config/wayfire.ini");let morePi_ish=!1;if(!autostartDir.endsWith("-pi")){
const lxdePiCheckDir=path.join(userHome,".config/lxpanel/LXDE-pi");fs.existsSync(lxdePiCheckDir)&&(morePi_ish=!0,autostartDir+="-pi")}showStep(),write("Create or redeploy weatherService"+trailingSpace);let serviceScript=fs.readFileSync(serviceSrc).toString().replace(/\/pi\//g,`/${user}/`);usingNvm&&(serviceScript=serviceScript.replace(/^NODE_BIN_DIR=".*"/m,`NODE_BIN_DIR="${nodePath}"`)),fs.writeFileSync("/etc/init.d/weatherService",serviceScript),await(0,process_util_1.monitorProcess)((0,
process_util_1.spawn)("chmod",["+x","/etc/init.d/weatherService"],{shell:!0}),spin,process_util_1.ErrorMode.ANY_ERROR),writeSettings(),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("update-rc.d",["weatherService","defaults"]),spin),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("systemctl",["enable","weatherService"]),spin),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("mkdir",uid,["-p",autostartDir]),spin)
;let autoScript=fs.readFileSync(path.join(rpiSetupStuff,"autostart_extra.sh")).toString(),launchCmd=doFirefox?"firefox -new-window http://localhost:8080/":launchChromium
;doFullscreen&&!doFirefox?launchCmd=launchCmd.replace(/\s+/,' --new-window --start-fullscreen "${maxarg}" --autoplay-policy=no-user-gesture-required '):doKiosk&&!doFirefox?launchCmd=launchCmd.replace(/\s+/,' --kiosk "${maxarg}" --autoplay-policy=no-user-gesture-required '):(doKiosk||doFullscreen)&&doFirefox&&(launchCmd=launchCmd.replace("-new-window","--kiosk")),
autoScript=autoScript.replace("echo #launch-here",launchCmd).replace(/:8080\b/,":"+settings.AWC_PORT).replace("the-browser",doFirefox?"firefox":chromium).replace(/\/pi\//g,`/${user}/`),fs.writeFileSync(path.join(autostartDir,"autostart_extra.sh"),autoScript);const autostartPath=autostartDir+"/autostart",autostartEntry=autostartDir+"/autostart_extra.sh"+(doFirefox?" -f":"");let lines=[],update=!1,found=!1;try{lines=(0,util_1.asLines)(fs.readFileSync(autostartPath).toString()).filter((line=>!!line.trim()))
}catch(err){(isRaspberryPi||morePi_ish)&&(update=!0,lines=["@lxpanel --profile LXDE-pi","@pcmanfm --desktop --profile LXDE-pi","@xscreensaver -no-splash"],await isInstalled("point-rpi")&&lines.push("@point-rpi"))}for(let i=0;i<=lines.length;++i){if(i===lines.length&&!found){lines.push(autostartEntry),update=!0;break}autostartEntryPattern.test(lines[i])?found=!0:oldAutostartEntryPattern.test(lines[i])&&(lines.splice(i--,1),update=!0)}update&&fs.writeFileSync(autostartPath,lines.join("\n")+"\n");try{(0,
fs_1.existsSync)(wayfireIniPath)?lines=(0,util_1.asLines)(fs.readFileSync(wayfireIniPath).toString()).filter((line=>!!line.trimEnd())):(fs.mkdirSync(path.dirname(wayfireIniPath),{recursive:!0}),lines=[]);let autoIndex=lines.findIndex((l=>l.startsWith("[autostart]")));if(autoIndex<0)lines.push(""),lines.push("[autostart]"),autoIndex=lines.length;else for(;lines[++autoIndex]&&!/^((\s*\[)|(clock[12] = ))/.test(lines[autoIndex]););lines=lines.filter(((l,i)=>i<autoIndex||!/^clock[12] = /.test(l))),
lines.splice(autoIndex,0,"clock1 = "+autostartEntry),fs.writeFileSync(wayfireIniPath,lines.join("\n")+"\n")}catch(e){console.error(chalk.redBright("Error: failed to update .config/wayfire.ini to autostart AW-Clock")),console.error(chalk.redBright(" "+e.message))}const labwcAutostartPath=path.join(userHome,".config/labwc/autostart");try{(0,fs_1.existsSync)(labwcAutostartPath)?lines=(0,
util_1.asLines)(fs.readFileSync(labwcAutostartPath).toString()).filter((line=>!!line.trimEnd())):(fs.mkdirSync(path.dirname(labwcAutostartPath),{recursive:!0}),lines=[]);const autoIndex=lines.findIndex((l=>/\bautostart_extra.sh\b/.test(l)));autoIndex<0?lines.push(autostartEntry):lines[autoIndex]=autostartEntry,fs.writeFileSync(labwcAutostartPath,lines.join("\n")+"\n")}catch(e){console.error(chalk.redBright("Error: failed to update .config/labwc/autostart to autostart AW-Clock")),
console.error(chalk.redBright(" "+e.message))}await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("chown",0,[sudoUser,autostartDir+"/autostart*"],{shell:!0}),spin,process_util_1.ErrorMode.ANY_ERROR),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("chmod",uid,["+x",autostartDir+"/autostart*"],{shell:!0}),spin,process_util_1.ErrorMode.ANY_ERROR),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("chown",0,[sudoUser,wayfireIniPath],{shell:!0
}),spin,process_util_1.ErrorMode.ANY_ERROR),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("chown",0,[sudoUser,labwcAutostartPath],{shell:!0}),spin,process_util_1.ErrorMode.ANY_ERROR),noStop?console.log(backspace+trailingSpace+"\n\nReboot to complete set-up."):await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("service",["weatherService","start"]),spin),stepDone()}()),doLaunch){console.log(chalk.cyan(sol+"- Launching Astronomy/Weather Clock -")),showStep(),write(" "),await(0,
process_util_1.sleep)(3e3,spin),stepDone(),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("pkill",uid,["-o",chromium]),spin,process_util_1.ErrorMode.NO_ERRORS),await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("pkill",uid,["-o",chromium.substr(0,15)]),spin,process_util_1.ErrorMode.NO_ERRORS),await(0,process_util_1.sleep)(500,spin);const args=launchChromium.split(/\s/).slice(1);args.splice(args.length-1,0,`--user-data-dir='${userHome}'`),setTimeout((()=>process.exit(0)),5e3),
await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)(chromium,uid,args,{detached:!0}))}doReboot&&(console.log(chalk.cyan(sol+"- Rebooting system in 5 seconds... -")),showStep(),write("Press any key to stop reboot:"+trailingSpace),await(0,process_util_1.sleep)(5e3,spin,!0)?console.log():(console.log(),(0,child_process_1.exec)("reboot"))),process.exit(0)}catch(err){console.log(backspace+chalk.red("✘")),console.error(err),process.exit(1)}})()},
677:function(__unused_webpack_module,exports,__webpack_require__){var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0}),
exports.safeCompareVersions=exports.setAlertId=exports.checksum53=exports.alertCleanUp=exports.filterError=exports.unref=exports.timeStamp=exports.escapeForRegex=exports.checkForecastIntegrity=exports.getRemoteAddress=exports.hasGps=exports.roughDistanceBetweenLocationsInKm=exports.splitIpAndPort=exports.normalizePort=exports.autoInHg=exports.autoHpa=exports.hpaToInHg=exports.inHgToHpa=exports.milesToKm=exports.inchesToCm=exports.fToC=exports.stdDev=exports.average=exports.jsonOrJsonp=exports.noCache=void 0
;const math_1=__webpack_require__(72),process_util_1=__webpack_require__(990),util_1=__webpack_require__(714),compare_versions_1=__importDefault(__webpack_require__(323));function average(values){return values.reduce(((sum,value)=>sum+value))/values.length}function inHgToHpa(p){return 33.864*p}function hpaToInHg(p){return p/33.864}async function hasCommand(command){return!!(await(0,process_util_1.monitorProcess)((0,process_util_1.spawn)("which",[command]),null,process_util_1.ErrorMode.ANY_ERROR)).trim()}
exports.noCache=function(res){res.header("Cache-Control","private, no-cache, no-store, must-revalidate"),res.header("Expires","-1"),res.header("Pragma","no-cache")},exports.jsonOrJsonp=function(req,res,data){req.query.callback?res.jsonp(data):res.json(data)},exports.average=average,exports.stdDev=function(values){const avg=average(values),squaredDiffs=values.map((value=>{const diff=avg-value;return diff*diff}));return Math.sqrt(average(squaredDiffs))},exports.fToC=function(f){return(f-32)/1.8},
exports.inchesToCm=function(i){return 2.54*i},exports.milesToKm=function(m){return 1.609344*m},exports.inHgToHpa=inHgToHpa,exports.hpaToInHg=hpaToInHg,exports.autoHpa=function(p){return p>100?p:inHgToHpa(p)},exports.autoInHg=function(p){return p<100?p:hpaToInHg(p)},exports.normalizePort=function(val){const port=parseInt(val,10);return isNaN(port)?val:port>=0&&port},exports.splitIpAndPort=function(ipWithPossiblePort,defaultPort){if(!ipWithPossiblePort)return[void 0,defaultPort]
;let $=/^\[(.+)]:(\d+)$/.exec(ipWithPossiblePort);return $?[$[1],Number($[2])]:($=/^([^[:]+):(\d+)$/.exec(ipWithPossiblePort),$?[$[1],Number($[2])]:[ipWithPossiblePort,defaultPort])},exports.roughDistanceBetweenLocationsInKm=function(lat1,long1,lat2,long2){let deltaRad=(0,math_1.acos)((0,math_1.sin_deg)(lat1)*(0,math_1.sin_deg)(lat2)+(0,math_1.cos_deg)(lat1)*(0,math_1.cos_deg)(lat2)*(0,math_1.cos_deg)(long1-long2));for(;deltaRad>math_1.PI;)deltaRad-=math_1.PI;for(;deltaRad<-math_1.PI;)deltaRad+=math_1.PI
;return 6378.14*deltaRad},exports.hasGps=async function(){return await hasCommand("gpspipe")||await hasCommand("ntpq")},exports.getRemoteAddress=function(req){return req.headers["x-real-ip"]||req.socket.remoteAddress},exports.checkForecastIntegrity=function(forecast,currentOnly=!1){return(null==forecast?void 0:forecast.currently)&&(0,util_1.isNumber)(forecast.currently.temperature)&&(currentOnly||forecast.hourly&&forecast.hourly.length>23&&(0,
util_1.isNumber)(forecast.hourly[0].temperature)&&forecast.daily&&forecast.daily.data&&forecast.daily.data.length>3&&(0,util_1.isNumber)(forecast.daily.data[0].time))};const charsNeedingRegexEscape=/[-[\]/{}()*+?.\\^$|]/g;function checksum53(s,seed=0){let h1=3735928559^seed,h2=1103547991^seed;for(let ch,i=0;i<s.length;++i)ch=s.charCodeAt(i),h1=Math.imul(h1^ch,2654435761),h2=Math.imul(h2^ch,1597334677);return h1=Math.imul(h1^h1>>>16,2246822507)^Math.imul(h2^h2>>>13,3266489909),
h2=Math.imul(h2^h2>>>16,2246822507)^Math.imul(h1^h1>>>13,3266489909),(4294967296*(2097151&h2)+(h1>>>0)).toString(16).toUpperCase().padStart(14,"0")}exports.escapeForRegex=function(s){return s.replace(charsNeedingRegexEscape,"\\$&")},exports.timeStamp=function(){return"["+(new Date).toISOString()+"]"},exports.unref=function(timer){return(null==timer?void 0:timer.unref)&&timer.unref(),timer},exports.filterError=function(error){var _a
;return(error=null!==(_a=null==error?void 0:error.message)&&void 0!==_a?_a:null==error?void 0:error.toString())&&error.replace(/^\s*Error:\s*/i,"")},exports.alertCleanUp=function(alertText){if(!/[\u0100-\uFFFF]/.test(alertText)&&/[\u00C0-\u00DF][\u0080-\u00BF]|([\u00E0-\u00EF][\u0080-\u00BF]{2})|([\u00F0-\u00F7][\u0080-\u00BF]{3})/.test(alertText)){const altText=Buffer.from(alertText,"latin1").toString("utf8");altText.length<alertText.length&&(alertText=altText)}
let alert=alertText.trim().replace(/(?<=issued an?)\n\n?\* /g," ").replace(/\bfor\.\.\.\n.*?\n\n?\* /s,(match=>{let goodLines=!0;const lines=match.split("\n").filter((line=>!!line)).slice(1,-1).map((line=>line.endsWith("...")?"• "+line.trim().slice(0,-3):(goodLines=!1,line)));return goodLines?"for:\n\n"+lines.join("\n")+"\n\n* ":match
})).replace(/\.\.\.\n\*\s+([A-Z]{3,})\.\.\./g,".\n\n• $1: ").replace(/^((\* )?(WHAT|WHERE|WHEN|IMPACTS?|HAZARD|SOURCE))\.\.\./gm,"\n• $3: ").replace(/^- (?=\w)/gm," ◦ ").replace(/([12]?\d)([0-5]\d) ([AP]M)/g,"$1:$2 $3").replace(/^(.*)\.\.\.\s{3,}(.*?)(\.\.\.)?\n/gm,((match,$1,$2,$3)=>match.substring(0,35).endsWith(" ")?$3?`${$1}, ${$2}, `:`${$1}, ${$2} `:match)).replace(/^(?<!.*\.\.\.\s{3,}.*)\.\.\.\n/gm,":\n").replace(/(?<!\.)\.\n\.\.\./g,".\n\n").replace(/\.\.\.\n/g,":\n\n").replace(/^\.(?=\w)/gm,"").replace(/^[ \t]*\.{3,}/gm,"").replace(/&&\s*$/,"").replace(/&&/g,"⚠︎").replace(/\n{3,}/g,"\n\n").trim()
;return alert.startsWith("•")&&(alert="\n\n"+alert),alert},exports.checksum53=checksum53,exports.setAlertId=function(alert){return alert.id=checksum53(`${alert.title}\t${alert.description}\t${alert.severity}`),alert},exports.safeCompareVersions=function(firstVersion,secondVersion,operatorOrDefValue,defValue=!1){try{return(0,
util_1.isString)(operatorOrDefValue)?compare_versions_1.default.compare(firstVersion,secondVersion,operatorOrDefValue):(operatorOrDefValue=null!=operatorOrDefValue?operatorOrDefValue:-1,(0,compare_versions_1.default)(firstVersion,secondVersion))}catch(_a){}return(0,util_1.isString)(operatorOrDefValue)?defValue:operatorOrDefValue}},990:function(__unused_webpack_module,exports,__webpack_require__){var __createBinding=this&&this.__createBinding||(Object.create?function(o,m,k,k2){void 0===k2&&(k2=k)
;var desc=Object.getOwnPropertyDescriptor(m,k);desc&&!("get"in desc?!m.__esModule:desc.writable||desc.configurable)||(desc={enumerable:!0,get:function(){return m[k]}}),Object.defineProperty(o,k2,desc)}:function(o,m,k,k2){void 0===k2&&(k2=k),o[k2]=m[k]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(o,v){Object.defineProperty(o,"default",{enumerable:!0,value:v})}:function(o,v){o.default=v}),__importStar=this&&this.__importStar||function(mod){if(mod&&mod.__esModule)return mod
;var result={};if(null!=mod)for(var k in mod)"default"!==k&&Object.prototype.hasOwnProperty.call(mod,k)&&__createBinding(result,mod,k);return __setModuleDefault(result,mod),result};Object.defineProperty(exports,"__esModule",{value:!0}),exports.sleep=exports.monitorProcessLines=exports.monitorProcess=exports.spawn=exports.stripFormatting=exports.ErrorMode=exports.getSudoUser=exports.getUserHome=void 0
;const child_process_1=__webpack_require__(317),readline=__importStar(__webpack_require__(785)),util_1=__webpack_require__(714),isMacOS="darwin"===process.platform,isWindows="win32"===process.platform,sudoUser=process.env.SUDO_USER||process.env.USER||"pi";let userHome="/home/pi";try{userHome=isMacOS?process.env.HOME:isWindows?process.env.USERPROFILE:(0,child_process_1.execSync)(`grep ${sudoUser} /etc/passwd`).toString().split(":")[5]||userHome}catch(err){console.error(err)}var ErrorMode
;exports.getUserHome=function(){return userHome},exports.getSudoUser=function(){return sudoUser},function(ErrorMode){ErrorMode[ErrorMode.DEFAULT=0]="DEFAULT",ErrorMode[ErrorMode.ANY_ERROR=1]="ANY_ERROR",ErrorMode[ErrorMode.NO_ERRORS=2]="NO_ERRORS"}(ErrorMode=exports.ErrorMode||(exports.ErrorMode={}));const NO_OP=()=>{};function stripFormatting(s){return null==s?void 0:s.replace(/\x1B\[[\d;]*[A-Za-z]/g,"")}function errorish(s){return s=stripFormatting(s),
/\b(failed|exception|invalid|operation not permitted|isn't a valid|Cannot resolve|must be specified|must implement|need to install|doesn't exist|are required|should be strings?)\b/i.test(s)||/[_\da-z](Error|Exception|Invalid)\b/.test(s)||/\[ERR_|code: 'ERR/.test(s)}function monitorProcess(proc,markTime=void 0,errorMode=ErrorMode.DEFAULT){let errors="",output="";return new Promise(((resolve,reject)=>{const slowSpin=((null==(timer=setInterval(markTime||NO_OP,100))?void 0:timer.unref)&&timer.unref(),timer)
;var timer;proc.stderr.on("data",(data=>{(markTime||NO_OP)(),data=stripFormatting(data.toString()),/(\[webpack.Progress])|Warning\b/.test(data)||(errors+=data)})),proc.stdout.on("data",(data=>{(markTime||NO_OP)(),data=data.toString(),output+=data,errorish(data)&&(errors=errors?errors+"\n"+data:data)})),proc.on("error",(err=>{clearInterval(slowSpin),errorMode===ErrorMode.NO_ERRORS?resolve(output):reject(err)})),proc.on("close",(()=>{clearInterval(slowSpin),
errorMode!==ErrorMode.NO_ERRORS&&errors&&(errorMode===ErrorMode.ANY_ERROR||errorish(errors))?reject(errors.replace(/\bE:\s+/g,"").trim()):resolve(output)}))}))}exports.stripFormatting=stripFormatting,exports.spawn=function(command,uidOrArgs,optionsOrArgs,options){let uid,args;if((0,util_1.isNumber)(uidOrArgs)?(uid=uidOrArgs,args=optionsOrArgs||[]):(args=uidOrArgs||[],uid=null==(options=optionsOrArgs)?void 0:options.uid),null!=uid&&((options=null!=options?options:{}).uid=uid,options.env||(options.env={},
Object.assign(options.env,process.env)),options.env.HOME=userHome,options.env.LOGNAME=sudoUser,options.env.npm_config_cache=userHome+"/.npm",options.env.USER=sudoUser),isWindows){/^(chmod|chown|id)$/.test(command)?(command="rundll32",args=[]):"rm"===command?(command="rmdir",args=["/S","/Q",args[1].replace(/\//g,"\\")]):"which"===command&&(command="where");const cmd=process.env.comspec||"cmd";return null!=(null==options?void 0:options.uid)&&delete(options=Object.assign({},options)).uid,(0,
child_process_1.spawn)(cmd,["/c",command,...args],options)}return(0,child_process_1.spawn)(command,args,options)},exports.monitorProcess=monitorProcess,exports.monitorProcessLines=async function(proc,markTime=void 0,errorMode=ErrorMode.DEFAULT){return(0,util_1.asLines)(await monitorProcess(proc,markTime,errorMode))},exports.sleep=function(delay,markTime=void 0,stopOnKeypress=!1){return new Promise((resolve=>{const slowSpin=setInterval(markTime||NO_OP,100),timeout=setTimeout((()=>{clearInterval(slowSpin),
resolve(!1)}),delay);stopOnKeypress&&(readline.emitKeypressEvents(process.stdin),process.stdin.setRawMode(!0),process.stdin.on("keypress",(()=>{clearInterval(slowSpin),clearTimeout(timeout),resolve(!0)})))}))}},283:function(__unused_webpack_module,exports,__webpack_require__){var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.convertPinToGpio=exports.convertPin=exports.PinSystem=void 0
;const fs_1=__importDefault(__webpack_require__(896)),util_1=__webpack_require__(714),wpiToGpioR1=[17,18,21,22,23,24,25,4,0,1,8,7,10,9,11,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];let wpiToGpio=[17,18,27,22,23,24,25,4,2,3,8,7,10,9,11,14,15,28,29,30,31,5,6,13,19,26,12,16,20,21,0,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]
;const physToGpioR1=[-1,-1,-1,0,-1,1,-1,4,14,-1,15,17,18,21,-1,22,23,-1,24,10,-1,9,25,11,8,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];let physToGpio=[-1,-1,-1,2,-1,3,-1,4,14,-1,15,17,18,27,-1,22,23,-1,24,10,-1,9,25,11,8,-1,7,0,1,5,-1,6,12,13,-1,19,16,26,20,-1,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,28,29,30,31,-1,-1,-1,-1,-1,-1,-1];var GpioLayout,PinSystem;!function(GpioLayout){GpioLayout[GpioLayout.UNCHECKED=0]="UNCHECKED",
GpioLayout[GpioLayout.LAYOUT_1=1]="LAYOUT_1",GpioLayout[GpioLayout.LAYOUT_2=2]="LAYOUT_2",GpioLayout[GpioLayout.UNKNOWN=3]="UNKNOWN"}(GpioLayout||(GpioLayout={})),function(PinSystem){PinSystem[PinSystem.GPIO=0]="GPIO",PinSystem[PinSystem.PHYS=1]="PHYS",PinSystem[PinSystem.WIRING_PI=2]="WIRING_PI",PinSystem[PinSystem.VIRTUAL=2]="VIRTUAL"}(PinSystem=exports.PinSystem||(exports.PinSystem={}));let gpioLayout=GpioLayout.UNCHECKED,supportPhysPins=!1;let convertInit=!1
;const gpioToPhys=new Array(32).fill(-1),gpioToWPi=new Array(32).fill(-1);function getConversions(){if(function(){if(gpioLayout===GpioLayout.UNCHECKED){let lines;gpioLayout=GpioLayout.UNKNOWN;try{lines=(0,util_1.asLines)(fs_1.default.readFileSync("/proc/cpuinfo",{encoding:"ascii"}))}catch(_a){return void console.error("Can't read /proc/cpuinfo")}for(const line of lines){const $=/^Revision\s*:\s*\w*(\w{4})$/.exec(line);if($){"0002"===$[1]||"0003"===$[1]?(gpioLayout=GpioLayout.LAYOUT_1,wpiToGpio=wpiToGpioR1,
physToGpio=physToGpioR1):gpioLayout=GpioLayout.LAYOUT_2,supportPhysPins=!0;break}}}}(),!convertInit&&gpioLayout!==GpioLayout.UNKNOWN){for(let i=0;i<64;++i){let gpio=wpiToGpio[i];gpio>=0&&(gpioToWPi[gpio]=i),gpio=physToGpio[i],gpio>=0&&(gpioToPhys[gpio]=i)}convertInit=!0}}function convertPin(pin,pinSystem0,pinSystem1){let pinNumber,pinSystemFrom,pinSystemTo;if((0,util_1.isString)(pin)){const $=/^(\d+)\s*([gpvw]?)$/.exec(pin.trim().toLowerCase());if(!$)return-1;{pinNumber=parseFloat($[1]),
pinNumber=isNaN(pinNumber)?-1:pinNumber;const pinSystemIndex="pvw".indexOf($[2]||"g")+1;pinSystemFrom=[PinSystem.GPIO,PinSystem.PHYS,PinSystem.VIRTUAL,PinSystem.WIRING_PI][pinSystemIndex],pinSystemTo=pinSystem0}}else pinNumber=pin,null==pinSystem1?(pinSystemFrom=PinSystem.GPIO,pinSystemTo=pinSystem0):(pinSystemFrom=pinSystem0,pinSystemTo=pinSystem1);return function(pinNumber,pinSysFrom,pinSysTo){if(getConversions(),
!(supportPhysPins||pinSysFrom!==PinSystem.PHYS&&pinSysTo!==PinSystem.PHYS))throw new Error("Unknown hardware - physical pin numbering not supported");if(pinNumber<0||pinNumber>63||pinSysFrom!==PinSystem.PHYS&&pinNumber>31)return-1;let gpio;switch(pinSysFrom){case PinSystem.GPIO:switch(pinSysTo){case PinSystem.GPIO:return pinNumber;case PinSystem.PHYS:return gpioToPhys[pinNumber];case PinSystem.WIRING_PI:return gpioToWPi[pinNumber]}break;case PinSystem.PHYS:switch(pinSysTo){case PinSystem.GPIO:
return physToGpio[pinNumber];case PinSystem.PHYS:return pinNumber;case PinSystem.WIRING_PI:return(gpio=physToGpio[pinNumber])>=0?gpioToWPi[gpio]:-1}break;case PinSystem.WIRING_PI:switch(pinSysTo){case PinSystem.GPIO:return wpiToGpio[pinNumber];case PinSystem.PHYS:return(gpio=wpiToGpio[pinNumber])>=0?gpioToPhys[gpio]:-1;case PinSystem.WIRING_PI:return pinNumber}}return-1}(pinNumber,pinSystemFrom,pinSystemTo)}exports.convertPin=convertPin,exports.convertPinToGpio=function(pinNumber,pinSys=PinSystem.GPIO){
return(0,util_1.isString)(pinNumber)?convertPin(pinNumber,PinSystem.GPIO):convertPin(pinNumber,pinSys,PinSystem.GPIO)}},72:module=>{module.exports=require("@tubular/math")},714:module=>{module.exports=require("@tubular/util")},895:module=>{module.exports=require("chalk")},323:module=>{module.exports=require("compare-versions")},980:module=>{module.exports=require("copyfiles")},317:module=>{module.exports=require("child_process")},896:module=>{module.exports=require("fs")},857:module=>{
module.exports=require("os")},928:module=>{module.exports=require("path")},785:module=>{module.exports=require("readline")},23:module=>{module.exports=require("util")}},__webpack_module_cache__={};(function __webpack_require__(moduleId){var cachedModule=__webpack_module_cache__[moduleId];if(void 0!==cachedModule)return cachedModule.exports;var module=__webpack_module_cache__[moduleId]={exports:{}};return __webpack_modules__[moduleId].call(module.exports,module,module.exports,__webpack_require__),
module.exports})(121)})();