/**
 * Minified by jsDelivr using Terser v5.39.0.
 * Original file: /npm/@frangoteam/fuxa-min@1.3.1/main.js
 *
 * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
 */
#!/usr/bin/env node
const fs=require("fs"),path=require("path"),morgan=require("morgan"),http=require("http"),https=require("https"),socketIO=require("socket.io"),nopt=require("nopt"),schedule=require("node-schedule"),paths=require("./paths"),logger=require("./runtime/logger"),utils=require("./runtime/utils");var events=require("./runtime/events").create();const FUXA=require("./fuxa.js"),runtime=require("./runtime"),authJwt=require("./api/jwt-helper"),express=require("express"),app=express();var server,settingsFile,startTime=new Date,knownOpts={help:Boolean,port:Number,userDir:[path]},shortHands={"?":["--help"],p:["--port"],u:["--userDir"]};nopt.invalidHandler=function(e,s,t){};var parsedArgs=nopt(knownOpts,shortHands,process.argv,2);parsedArgs.help&&(console.log("FUXA v"+FUXA.version()),console.log("Usage: fuxa [-?] [--port PORT] [--userDir DIR]"),console.log(""),console.log("Options:"),console.log("  -p, --port     PORT  port to listen on"),console.log("  -u, --userDir  DIR   use specified user directory"),console.log("  -?, --help           show this help"),process.exit());var rootDir=__dirname,workDir=path.resolve(process.cwd(),"_appdata");process.env.userDir&&(rootDir=process.env.userDir,workDir=path.resolve(process.env.userDir,"_appdata")),parsedArgs.userDir&&(rootDir=parsedArgs.userDir,workDir=path.resolve(parsedArgs.userDir,"_appdata")),parsedArgs.env&&require("./envParams.js"),fs.existsSync(workDir)||fs.mkdirSync(workDir);var appSettingsFile=path.join(workDir,"settings.js");if(fs.existsSync(appSettingsFile))settingsFile=appSettingsFile;else{var defaultSettings=path.join(__dirname,"settings.default.js");try{fs.copyFileSync(defaultSettings,appSettingsFile,fs.constants.COPYFILE_EXCL),logger.debug("settings.js default created successful!")}catch(e){logger.error(e)}settingsFile=appSettingsFile}try{var settings=require(settingsFile),defSettings=require(path.join(__dirname,"settings.default.js"));defSettings.version!==settings.version&&(logger.warn("Settings are outdated. Missing fields have been merged from defaults. Consider reviewing 'settings.json'."),settings=utils.deepMerge(defSettings,settings)),settings.workDir=workDir,settings.appDir=__dirname,settings.packageDir=path.resolve(rootDir,"_pkg"),settings.settingsFile=settingsFile,settings.environment=process.env.NODE_ENV||"prod",settings.uploadFileDir="_upload_files",settings.imagesFileDir=path.resolve(rootDir,"_images"),settings.widgetsFileDir=path.resolve(rootDir,"_widgets"),settings.reportsDir=path.resolve(rootDir,"_reports"),settings.webcamSnapShotsDir=path.resolve(rootDir,settings.webcamSnapShotsDir),settings.logDir=path.resolve(rootDir,settings.logDir),settings.dbDir=path.resolve(rootDir,settings.dbDir||"_db")}catch(e){logger.error("Error loading settings file: "+settingsFile),"MODULE_NOT_FOUND"==e.code?-1===e.toString().indexOf(settingsFile)&&logger.error(e.toString()):logger.error(e),process.exit()}try{var userSettingsFile=path.join(workDir,"mysettings.json");if(settings.userSettingsFile=userSettingsFile,fs.existsSync(userSettingsFile)){var mysettings=JSON.parse(fs.readFileSync(userSettingsFile,"utf8"));mysettings.language&&(settings.language=mysettings.language),utils.isNullOrUndefined(mysettings.hideEditorOnboarding)||(settings.hideEditorOnboarding=mysettings.hideEditorOnboarding),mysettings.uiPort&&(settings.uiPort=mysettings.uiPort),utils.isNullOrUndefined(mysettings.secureEnabled)||(settings.secureEnabled=mysettings.secureEnabled,settings.tokenExpiresIn||(settings.tokenExpiresIn="1h")),utils.isNullOrUndefined(mysettings.secureOnlyEditor)||(settings.secureOnlyEditor=mysettings.secureOnlyEditor),mysettings.tokenExpiresIn&&(settings.tokenExpiresIn=mysettings.tokenExpiresIn),utils.isNullOrUndefined(mysettings.enableRefreshCookieAuth)||(settings.enableRefreshCookieAuth=mysettings.enableRefreshCookieAuth),mysettings.refreshTokenExpiresIn&&(settings.refreshTokenExpiresIn=mysettings.refreshTokenExpiresIn),mysettings.secretCode&&(settings.secretCode=mysettings.secretCode),mysettings.smtp&&(settings.smtp=mysettings.smtp),mysettings.daqstore&&(settings.daqstore=mysettings.daqstore),mysettings.alarms&&(settings.alarms=mysettings.alarms),mysettings.logs&&(settings.logs=mysettings.logs),utils.isNullOrUndefined(mysettings.broadcastAll)||(settings.broadcastAll=mysettings.broadcastAll),utils.isNullOrUndefined(mysettings.logFull)||(settings.logFull=mysettings.logFull),utils.isNullOrUndefined(mysettings.userRole)||(settings.userRole=mysettings.userRole),utils.isNullOrUndefined(mysettings.nodeRedEnabled)||(settings.nodeRedEnabled=mysettings.nodeRedEnabled),utils.isNullOrUndefined(mysettings.nodeRedAuthMode)||(settings.nodeRedAuthMode=mysettings.nodeRedAuthMode),utils.isNullOrUndefined(mysettings.swaggerEnabled)||(settings.swaggerEnabled=mysettings.swaggerEnabled),!0===mysettings.nodeRedEnabled&&utils.isNullOrUndefined(mysettings.nodeRedAuthMode)&&(settings.nodeRedAuthMode="legacy-open")}}catch(e){logger.error("Error loading user settings file: "+userSettingsFile)}settings.secureEnabled&&!settings.secretCode&&(settings.secretCode=utils.generateSecretCode(),logger.warn("Generated a random JWT secret in memory because secureEnabled=true and secretCode was missing. Persist it in settings for stable sessions across restarts.")),settings.logDir||(settings.logDir=path.resolve(rootDir,"_logs")),fs.existsSync(settings.logDir)||fs.mkdirSync(settings.logDir),logger.init(settings);const version=FUXA.version();version.indexOf("beta")>0?logger.warn("FUXA V."+version):logger.info("FUXA V."+version),fs.existsSync(settings.dbDir)||fs.mkdirSync(settings.dbDir),fs.existsSync(settings.packageDir)||fs.mkdirSync(settings.packageDir),fs.existsSync(settings.reportsDir)||fs.mkdirSync(settings.reportsDir),settings.httpUploadFileStatic="resources",settings.uploadFileDir=path.resolve(workDir,settings.uploadFileDir),fs.existsSync(settings.uploadFileDir)||fs.mkdirSync(settings.uploadFileDir),fs.existsSync(settings.imagesFileDir)||fs.mkdirSync(settings.imagesFileDir),fs.existsSync(settings.widgetsFileDir)||fs.mkdirSync(settings.widgetsFileDir),fs.existsSync(settings.webcamSnapShotsDir)||fs.mkdirSync(settings.webcamSnapShotsDir),(server=settings.https?https.createServer(settings.https,app):http.createServer(app)).setMaxListeners(0);const io=socketIO(server,{pingInterval:6e4,pingTimeout:12e4,allowEIO3:!0,cors:{origin:"*",methods:["GET","POST"],credentials:!1}});var www=path.resolve(__dirname,"../client/dist");fs.existsSync(www)||(www=path.resolve(__dirname,"./dist")),settings.httpStatic=settings.httpStatic||www,void 0!==parsedArgs.port?settings.uiPort=parsedArgs.port:void 0===settings.uiPort&&(settings.uiPort=1881),settings.uiHost=settings.uiHost||"0.0.0.0",events.once("init-runtime-ok",(function(){logger.info("FUXA init in  "+utils.endTime(startTime)+"ms."),startFuxa(),initWebcamSnapshotCleanup()}));try{FUXA.init(server,io,settings,logger,events)}catch(e){"unsupported_version"==e.code?(logger.error("Unsupported version of node.js:",process.version),logger.error("FUXA requires node.js v6 or later")):"not_built"==e.code?logger.error("FUXA has not been built. See README.md for details"):(logger.error("Failed to start server:"),e.stack?logger.error(e.stack):logger.error(e)),process.exit(1)}const allowCrossDomain=function(e,s,t){const i=e.headers.origin,r=settings.allowedOrigins||["*"];if((e=>!!e&&(!!r.includes("*")||r.some((s=>{if(!s.includes("*"))return s===e;return new RegExp("^"+s.replace(/\./g,"\\.").replace(/\*/g,".*")+"$").test(e)}))))(i)&&(s.header("Access-Control-Allow-Origin",i||"*"),settings.enableRefreshCookieAuth&&s.header("Access-Control-Allow-Credentials","true")),s.header("Access-Control-Allow-Methods","GET,PUT,POST,DELETE,OPTIONS"),s.header("Access-Control-Allow-Headers","x-access-token, x-auth-user, Origin, Content-Type, Accept, Skip-Auth, Skip-Error"),"OPTIONS"===e.method)return s.sendStatus(204);t()};app.use(allowCrossDomain),app.use("/",express.static(settings.httpStatic)),app.use("/home",express.static(settings.httpStatic)),app.use("/home/:viewName",express.static(settings.httpStatic)),app.use("/lab",express.static(settings.httpStatic)),app.use("/editor",express.static(settings.httpStatic)),app.use("/device",express.static(settings.httpStatic)),app.use("/rodevice",express.static(settings.httpStatic)),app.use("/users",express.static(settings.httpStatic)),app.use("/view",express.static(settings.httpStatic)),app.use("/"+settings.httpUploadFileStatic,express.static(settings.uploadFileDir)),app.use("/_images",express.static(settings.imagesFileDir)),app.use("/_widgets",express.static(settings.widgetsFileDir)),app.use("/snapshots",express.static(settings.webcamSnapShotsDir));var accessLogStream=fs.createWriteStream(settings.logDir+"/api.log",{flags:"a"});function mountSwaggerIfEnabled(){if(!(settings.swagger||settings.swaggerEnabled))return;let e,s;try{e=require("swagger-ui-express"),s=require("yamljs")}catch(e){if(e&&"MODULE_NOT_FOUND"!==e.code)throw e;return void logger.warn("[Swagger] Enabled but optional dependencies are missing; skipping /api-docs. Install swagger-ui-express and yamljs to enable it.")}const t=s.load(path.join(__dirname,"docs","openapi.yaml"));app.use("/api-docs",e.serve,e.setup(t))}"none"!==runtime.settings.logApiLevel&&(app.use(morgan("combined",{stream:accessLogStream,skip:function(e,s){return s.statusCode<400}})),app.use(morgan("dev",{skip:function(e,s){return s.statusCode<400},stream:process.stderr})),app.use(morgan("dev",{skip:function(e,s){return s.statusCode>=400},stream:process.stdout})));try{mountSwaggerIfEnabled()}catch(e){logger.warn("Swagger UI failed to initialize",e)}function getListenPath(){var e=settings.serverPort;void 0===e&&(e=settings.uiPort);var s="http"+(settings.https?"s":"")+"://"+("::"==settings.uiHost?"localhost":"0.0.0.0"==settings.uiHost?"127.0.0.1":settings.uiHost)+":"+e;return settings.httpStatic&&(s+="/"),s}let mountNodeRedIfInstalled;function startFuxa(){FUXA.start().then((async()=>{if(settings.httpStatic){if(server.on("error",(function(e){"EADDRINUSE"===e.errno?(logger.error("server.port-in-use"),logger.error("server.unable-to-listen ",{listenpath:getListenPath()})):e.stack?logger.error(e.stack):logger.error("server.error "+e),process.exit(1)})),settings.nodeRedEnabled&&"function"==typeof mountNodeRedIfInstalled)try{await mountNodeRedIfInstalled({app:app,server:server,settings:settings,runtime:runtime,logger:logger,authJwt:authJwt,events:events})}catch(e){logger.warn("[Node-RED] Failed to initialize, continuing without it.",e)}else settings.nodeRedEnabled&&logger.warn("[Node-RED] Enabled but integration not available; continuing without it.");!1!==settings.disableServer&&app.use("/",FUXA.httpApi),server.listen(settings.uiPort,settings.uiHost,(function(){settings.serverPort=server.address().port,process.title="FUXA",logger.info("WebServer is running "+getListenPath())}))}else logger.info("server.headless-mode")})).catch((function(e){logger.error("server.failed-to-start"),e&&(e.stack?logger.error(e.stack):logger.error(e))}))}settings.nodeRedEnabled&&({mountNodeRedIfInstalled:mountNodeRedIfInstalled}=require("./integrations/node-red"));const initWebcamSnapshotCleanup=()=>{settings.webcamSnapShotsCleanup&&(schedule.scheduleJob("0 1 * * *",cleanupSnapShotsFiles),logger.info("Scheduled webcam snapshot cleanup at 01:00 daily."))},cleanupSnapShotsFiles=async()=>{const{webcamSnapShotsCleanup:e,webcamSnapShotsDir:s,webcamSnapShotsRetain:t}=settings;if(e)try{const e=Date.now(),i=24*t*60*60*1e3,r=await fs.promises.readdir(s);let n=0;for(const t of r){const r=path.join(s,t);try{const s=await fs.promises.stat(r);s.mtime&&e-s.mtimeMs>i&&(await fs.promises.unlink(r),n++)}catch(e){logger.error(`Failed to process snapshot file: ${r}`,e)}}logger.info(`Snapshot cleanup completed. ${n} old file(s) deleted.`)}catch(e){logger.error("Error during webcam snapshot cleanup",e)}};setTimeout((()=>{events.emit("init-runtime-ok")}),6e4),process.on("uncaughtException",(function(e){e.stack?logger.error(e.stack):logger.error(e)})),process.on("SIGINT",(function(){FUXA.stop().then((function(){process.exit()})),logger.info("FUXA end!"),process.exit()}));
//# sourceMappingURL=/sm/2969d2bc45460f9b7b71ba6632e037aa022139d8e65b2c1caea70ebe92502576.map