flightdeck 0.4.11 → 0.4.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/flightdeck.lib-Dfs4xGO7.js.map +1 -1
- package/dist/lib.d.ts.map +1 -1
- package/gen/lnav-format-schema.gen.ts +104 -116
- package/package.json +12 -12
- package/src/flightdeck.lib.ts +5 -4
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flightdeck.lib-Dfs4xGO7.js","names":[],"sources":["../src/flightdeck.env.ts","../src/flightdeck.lib.ts"],"sourcesContent":["import { createEnv } from \"@t3-oss/env-core\"\nimport { type } from \"arktype\"\n\nexport const env = createEnv({\n\tserver: { FLIGHTDECK_SECRET: type(`string`, `|`, `undefined`) },\n\tclientPrefix: `NEVER`,\n\tclient: {},\n\truntimeEnv: import.meta.env,\n\temptyStringAsUndefined: true,\n})\n","/* eslint-disable @typescript-eslint/only-throw-error */\nimport type { ChildProcessWithoutNullStreams } from \"node:child_process\"\nimport { execSync, spawn } from \"node:child_process\"\nimport { createServer } from \"node:http\"\nimport { homedir } from \"node:os\"\nimport { resolve } from \"node:path\"\nimport { inspect } from \"node:util\"\n\nimport { Future } from \"atom.io/internal\"\nimport { discoverType } from \"atom.io/introspection\"\nimport { fromEntries, toEntries } from \"atom.io/json\"\nimport { ChildSocket } from \"atom.io/realtime-server\"\nimport { CronJob } from \"cron\"\nimport { FilesystemStorage } from \"safedeposit\"\n\nimport type { LnavFormat } from \"../gen/lnav-format-schema.gen.ts\"\nimport { env } from \"./flightdeck.env.ts\"\n\nexport const FLIGHTDECK_SETUP_PHASES = [`downloaded`, `installed`] as const\n\nexport type FlightDeckSetupPhase = (typeof FLIGHTDECK_SETUP_PHASES)[number]\n\nexport const FLIGHTDECK_UPDATE_PHASES = [`notified`, `confirmed`] as const\n\nexport type FlightDeckUpdatePhase = (typeof FLIGHTDECK_UPDATE_PHASES)[number]\n\nexport function isVersionNumber(version: string): boolean {\n\treturn (\n\t\t/^\\d+\\.\\d+\\.\\d+$/.test(version) || !Number.isNaN(Number.parseFloat(version))\n\t)\n}\n\nexport type FlightDeckSaveData = {\n\tcurrentPid: `${number}`\n\tsetupPhase: FlightDeckSetupPhase\n\tupdatePhase: FlightDeckUpdatePhase\n\tupdateAwaitedVersion: string\n}\n\nexport type FlightDeckOptions<S extends string = string> = {\n\treadonly packageName: string\n\treadonly services: { [service in S]: { run: string; waitFor: boolean } }\n\treadonly scripts: {\n\t\treadonly download: string\n\t\treadonly install: string\n\t\treadonly checkAvailability?: string\n\t}\n\treadonly port?: number | undefined\n\treadonly flightdeckRootDir?: string | undefined\n\treadonly jsonLogging?: boolean | undefined\n}\n\nasync function waitForPidExit(pid: number, timeoutMs = 5000, intervalMs = 100) {\n\treturn new Promise<void>((pass, fail) => {\n\t\tconst start = Date.now()\n\n\t\tconst check = () => {\n\t\t\tprocess.stdout.write(`.`)\n\t\t\ttry {\n\t\t\t\t// check existence\n\t\t\t\tprocess.kill(pid, 0)\n\t\t\t\t// process still alive\n\t\t\t\tif (Date.now() - start > timeoutMs) {\n\t\t\t\t\tfail(new Error(`Timeout waiting for PID ${pid}`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tsetTimeout(check, intervalMs)\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error && `code` in err) {\n\t\t\t\t\tif (err.code === `ESRCH`) {\n\t\t\t\t\t\tpass()\n\t\t\t\t\t\treturn // exited\n\t\t\t\t\t}\n\t\t\t\t\tif (err.code === `EPERM`) {\n\t\t\t\t\t\t// process is alive but protected\n\t\t\t\t\t\tif (Date.now() - start > timeoutMs) {\n\t\t\t\t\t\t\tfail(\n\t\t\t\t\t\t\t\tnew Error(`Timeout waiting for PID ${pid} (EPERM; still alive)`),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn setTimeout(check, intervalMs)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfail(err)\n\t\t\t\treturn // unexpected error\n\t\t\t}\n\t\t}\n\n\t\tcheck()\n\t})\n}\n\nexport class FlightDeck<S extends string = string> {\n\tpublic static async kill(\n\t\tflightdeckRootDir: string,\n\t\tpackageName: string,\n\t): Promise<number> {\n\t\tconsole.info(`Killing FlightDeck instance of \"${packageName}\"`)\n\t\tconst storage = new FilesystemStorage<FlightDeckSaveData>({\n\t\t\tpath: resolve(flightdeckRootDir, `storage`, packageName),\n\t\t})\n\t\tconst currentPid = storage.getItem(`currentPid`)\n\t\tif (currentPid === null) {\n\t\t\tthrow new Error(`No pid for \"${packageName}\" found in storage`)\n\t\t}\n\t\tconst pid = Number(currentPid)\n\t\tconst now = Date.now()\n\t\tprocess.kill(pid, `SIGTERM`)\n\t\tawait waitForPidExit(pid, 5000, 5)\n\t\tconst elapsed = Date.now() - now\n\t\tprocess.stdout.write(\n\t\t\t`🌜 \"${packageName}\" (running as process ${pid}) exited in ${elapsed}ms\\n`,\n\t\t)\n\t\treturn pid\n\t}\n\n\tpublic readonly options: FlightDeckOptions<S>\n\tprotected safety = 0\n\n\tprotected storage: FilesystemStorage<FlightDeckSaveData>\n\tprotected services: {\n\t\t[service in S]: ChildSocket<\n\t\t\t{ timeToStop: []; updatesReady: [] },\n\t\t\t{ readyToUpdate: []; alive: [] },\n\t\t\tChildProcessWithoutNullStreams\n\t\t> | null\n\t}\n\tprotected serviceIdx: { readonly [service in S]: number }\n\tpublic defaultServicesReadyToUpdate: { readonly [service in S]: boolean }\n\tpublic servicesReadyToUpdate: { [service in S]: boolean }\n\tpublic autoRespawnDeadServices: boolean\n\n\tprotected logger: Pick<Console, `error` | `info` | `warn`>\n\tprotected serviceLoggers: {\n\t\treadonly [service in S]: FlightDeckLogger\n\t}\n\n\tprotected updateAvailabilityChecker: CronJob | null = null\n\n\tpublic servicesLive: Future<void>[]\n\tpublic servicesDead: Future<void>[]\n\tpublic live = new Future(() => {})\n\tpublic dead = new Future(() => {})\n\n\tprotected restartTimes: number[] = []\n\n\tpublic constructor(options: FlightDeckOptions<S>) {\n\t\tthis.options = options\n\t\tconst { FLIGHTDECK_SECRET } = env\n\t\tconst { flightdeckRootDir = resolve(homedir(), `.flightdeck`) } = options\n\t\tconst port = options.port ?? 8080\n\t\tconst origin = `http://localhost:${port}`\n\n\t\tconst servicesEntries = toEntries(options.services)\n\t\tthis.services = fromEntries(\n\t\t\tservicesEntries.map(([serviceName]) => [serviceName, null]),\n\t\t)\n\t\tthis.serviceIdx = fromEntries(\n\t\t\tservicesEntries.map(([serviceName], idx) => [serviceName, idx]),\n\t\t)\n\t\tthis.defaultServicesReadyToUpdate = fromEntries(\n\t\t\tservicesEntries.map(([serviceName, { waitFor }]) => [\n\t\t\t\tserviceName,\n\t\t\t\t!waitFor,\n\t\t\t]),\n\t\t)\n\t\tthis.servicesReadyToUpdate = { ...this.defaultServicesReadyToUpdate }\n\t\tthis.autoRespawnDeadServices = true\n\n\t\tthis.logger = new FlightDeckLogger(\n\t\t\tthis.options.packageName,\n\t\t\tprocess.pid,\n\t\t\tundefined,\n\t\t\t{ jsonLogging: this.options.jsonLogging ?? false },\n\t\t)\n\t\tthis.serviceLoggers = fromEntries(\n\t\t\tservicesEntries.map(([serviceName]) => [\n\t\t\t\tserviceName,\n\t\t\t\tnew FlightDeckLogger(\n\t\t\t\t\tthis.options.packageName,\n\t\t\t\t\tprocess.pid,\n\t\t\t\t\tserviceName,\n\t\t\t\t\t{ jsonLogging: this.options.jsonLogging ?? false },\n\t\t\t\t),\n\t\t\t]),\n\t\t)\n\n\t\tthis.servicesLive = servicesEntries.map(() => new Future(() => {}))\n\t\tthis.servicesDead = servicesEntries.map(() => new Future(() => {}))\n\t\tthis.live.use(Promise.all(this.servicesLive))\n\t\tthis.dead.use(Promise.all(this.servicesDead))\n\n\t\tthis.storage = new FilesystemStorage({\n\t\t\tpath: resolve(flightdeckRootDir, `storage`, options.packageName),\n\t\t})\n\n\t\tthis.storage.setItem(`currentPid`, `${process.pid}`)\n\n\t\tif (FLIGHTDECK_SECRET === undefined) {\n\t\t\tthis.logger.warn(\n\t\t\t\t`No FLIGHTDECK_SECRET environment variable found. FlightDeck will not run an update server.`,\n\t\t\t)\n\t\t} else {\n\t\t\tcreateServer((req, res) => {\n\t\t\t\tlet data: Uint8Array[] = []\n\t\t\t\treq\n\t\t\t\t\t.on(`data`, (chunk) => {\n\t\t\t\t\t\tdata.push(chunk instanceof Buffer ? chunk : Buffer.from(chunk))\n\t\t\t\t\t})\n\t\t\t\t\t.on(`end`, async () => {\n\t\t\t\t\t\tconst authHeader = req.headers.authorization\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (typeof req.url === `undefined`) throw 400\n\t\t\t\t\t\t\tconst expectedAuthHeader = `Bearer ${FLIGHTDECK_SECRET}`\n\t\t\t\t\t\t\tif (authHeader !== `Bearer ${FLIGHTDECK_SECRET}`) {\n\t\t\t\t\t\t\t\tthis.logger.info(\n\t\t\t\t\t\t\t\t\t`Unauthorized: needed \\`${expectedAuthHeader}\\`, got \\`${authHeader}\\``,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tthrow 401\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst url = new URL(req.url, origin)\n\t\t\t\t\t\t\tthis.logger.info(req.method, url.pathname)\n\n\t\t\t\t\t\t\tconst versionForeignInput = Buffer.concat(data).toString()\n\t\t\t\t\t\t\tif (!isVersionNumber(versionForeignInput)) {\n\t\t\t\t\t\t\t\tthrow 400\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tres.writeHead(200)\n\t\t\t\t\t\t\tres.end()\n\n\t\t\t\t\t\t\tthis.storage.setItem(`updatePhase`, `notified`)\n\t\t\t\t\t\t\tthis.storage.setItem(`updateAwaitedVersion`, versionForeignInput)\n\t\t\t\t\t\t\tconst { checkAvailability } = options.scripts\n\t\t\t\t\t\t\tif (checkAvailability) {\n\t\t\t\t\t\t\t\tawait this.updateAvailabilityChecker?.stop()\n\t\t\t\t\t\t\t\tawait this.seekUpdate(versionForeignInput)\n\t\t\t\t\t\t\t\tconst updatePhase = this.storage.getItem(`updatePhase`)\n\t\t\t\t\t\t\t\tthis.logger.info(`> storage(\"updatePhase\") >`, updatePhase)\n\t\t\t\t\t\t\t\tif (updatePhase === `notified`) {\n\t\t\t\t\t\t\t\t\tthis.updateAvailabilityChecker = new CronJob(\n\t\t\t\t\t\t\t\t\t\t`*/30 * * * * *`,\n\t\t\t\t\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\t\t\t\t\tawait this.seekUpdate(versionForeignInput)\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tthis.updateAvailabilityChecker.start()\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.downloadPackage()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (thrown) {\n\t\t\t\t\t\t\tthis.logger.error(thrown, req.url)\n\t\t\t\t\t\t\tif (typeof thrown === `number`) {\n\t\t\t\t\t\t\t\tres.writeHead(thrown)\n\t\t\t\t\t\t\t\tres.end()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tdata = []\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t}).listen(port, () => {\n\t\t\t\tthis.logger.info(`Server started on port ${port}`)\n\t\t\t})\n\t\t}\n\n\t\tthis.startAllServices()\n\t\t\t.then(() => {\n\t\t\t\tthis.logger.info(`All services started.`)\n\t\t\t})\n\t\t\t.catch((thrown) => {\n\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\tthis.logger.error(`Failed to start all services:`, thrown.message)\n\t\t\t\t}\n\t\t\t})\n\n\t\tprocess.on(`SIGTERM`, async () => {\n\t\t\tconsole.info(`Killed by SIGTERM`)\n\t\t\tawait this.stopAllServices()\n\t\t\tthis.storage.removeItem(`currentPid`)\n\t\t\tprocess.exit(0)\n\t\t})\n\t}\n\n\tprotected async seekUpdate(version: string): Promise<void> {\n\t\tthis.logger.info(`Checking for updates...`)\n\t\tconst { checkAvailability } = this.options.scripts\n\t\tif (!checkAvailability) {\n\t\t\tthis.logger.info(`No checkAvailability script found.`)\n\t\t\treturn\n\t\t}\n\t\ttry {\n\t\t\tconst out = execSync(`${checkAvailability} ${version}`)\n\t\t\tthis.logger.info(`Check stdout:`, out.toString())\n\t\t\tawait this.updateAvailabilityChecker?.stop()\n\t\t\tthis.storage.setItem(`updatePhase`, `confirmed`)\n\t\t\tthis.downloadPackage()\n\t\t\tthis.announceUpdate()\n\t\t} catch (thrown) {\n\t\t\tif (thrown instanceof Error) {\n\t\t\t\tthis.logger.error(`Check failed:`, thrown.message)\n\t\t\t} else {\n\t\t\t\tconst thrownType = discoverType(thrown)\n\t\t\t\tthis.logger.error(`Check threw`, thrownType, thrown)\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected announceUpdate(): void {\n\t\tfor (const entry of toEntries(this.services)) {\n\t\t\tconst [serviceName, service] = entry\n\t\t\tif (service) {\n\t\t\t\tif (this.options.services[serviceName].waitFor) {\n\t\t\t\t\tservice.emit(`updatesReady`)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.startService(serviceName)\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected tryUpdate(): void {\n\t\tif (toEntries(this.servicesReadyToUpdate).every(([, isReady]) => isReady)) {\n\t\t\tthis.logger.info(`All services are ready to update.`)\n\t\t\tthis.stopAllServices()\n\t\t\t\t.then(() => {\n\t\t\t\t\tthis.logger.info(`All services stopped; starting up fresh...`)\n\t\t\t\t\tthis.startAllServices()\n\t\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t\tthis.logger.info(`All services started; we're back online.`)\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch((thrown) => {\n\t\t\t\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t\t\t`Failed to start all services:`,\n\t\t\t\t\t\t\t\t\tthrown.message,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t\t.catch((thrown) => {\n\t\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\t\tthis.logger.error(`Failed to stop all services:`, thrown.message)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t}\n\t}\n\n\tprotected startAllServices(): Future<unknown> {\n\t\tthis.logger.info(`Starting all services...`)\n\t\tthis.autoRespawnDeadServices = true\n\t\tconst setupPhase = this.storage.getItem(`setupPhase`)\n\t\tthis.logger.info(`> storage(\"setupPhase\") >`, setupPhase)\n\t\tswitch (setupPhase) {\n\t\t\tcase null:\n\t\t\t\tthis.logger.info(`Starting from scratch.`)\n\t\t\t\tthis.downloadPackage()\n\t\t\t\tthis.installPackage()\n\t\t\t\treturn this.startAllServices()\n\t\t\tcase `downloaded`:\n\t\t\t\tthis.logger.info(`Found package downloaded but not installed.`)\n\t\t\t\tthis.installPackage()\n\t\t\t\treturn this.startAllServices()\n\t\t\tcase `installed`: {\n\t\t\t\tfor (const [serviceName] of toEntries(this.services)) {\n\t\t\t\t\tthis.startService(serviceName)\n\t\t\t\t}\n\t\t\t\treturn this.live\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected startService(serviceName: S): void {\n\t\tthis.logger.info(\n\t\t\t`Starting service ${this.options.packageName}::${serviceName}, try ${this.safety}/2...`,\n\t\t)\n\t\tif (this.safety >= 2) {\n\t\t\tthrow new Error(`Out of tries...`)\n\t\t}\n\t\tthis.safety++\n\n\t\tconst [exe, ...args] = this.options.services[serviceName].run.split(` `)\n\t\tconst serviceProcess = spawn(exe, args, {\n\t\t\tcwd: this.options.flightdeckRootDir,\n\t\t\tenv: import.meta.env,\n\t\t})\n\t\tconst serviceLogger = this.serviceLoggers[serviceName]\n\t\tconst service = (this.services[serviceName] = new ChildSocket(\n\t\t\tserviceProcess,\n\t\t\t`${this.options.packageName}::${serviceName}`,\n\t\t\tserviceLogger,\n\t\t))\n\t\tserviceLogger.processCode = service.proc.pid ?? -1\n\t\tthis.services[serviceName].onAny((...messages) => {\n\t\t\tserviceLogger.info(`💬`, ...messages)\n\t\t})\n\t\tthis.services[serviceName].on(`readyToUpdate`, () => {\n\t\t\tthis.logger.info(`Service \"${serviceName}\" is ready to update.`)\n\t\t\tthis.servicesReadyToUpdate[serviceName] = true\n\t\t\tthis.tryUpdate()\n\t\t})\n\t\tthis.services[serviceName].on(`alive`, () => {\n\t\t\tthis.servicesLive[this.serviceIdx[serviceName]].use(Promise.resolve())\n\t\t\tthis.servicesDead[this.serviceIdx[serviceName]] = new Future(() => {})\n\t\t\tif (this.dead.done) {\n\t\t\t\tthis.dead = new Future(() => {})\n\t\t\t}\n\t\t\tthis.dead.use(Promise.all(this.servicesDead))\n\t\t})\n\t\tthis.services[serviceName].proc.once(`close`, (exitCode) => {\n\t\t\tthis.logger.info(\n\t\t\t\t`Auto-respawn saw \"${serviceName}\" exit with code ${exitCode}`,\n\t\t\t)\n\t\t\tthis.services[serviceName] = null\n\t\t\tif (!this.autoRespawnDeadServices) {\n\t\t\t\tthis.logger.info(`😴 Auto-respawn is off; \"${serviceName}\" rests.`)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst updatePhase = this.storage.getItem(`updatePhase`)\n\t\t\tthis.logger.info(`> storage(\"updatePhase\") >`, updatePhase)\n\t\t\tconst updatesAreReady = updatePhase === `confirmed`\n\t\t\tif (updatesAreReady) {\n\t\t\t\tthis.serviceLoggers[serviceName].info(`Updating before startup...`)\n\t\t\t\tthis.restartTimes = []\n\t\t\t\tthis.installPackage()\n\t\t\t\tthis.startService(serviceName)\n\t\t\t} else {\n\t\t\t\tconst now = Date.now()\n\t\t\t\tconst fiveMinutesAgo = now - 5 * 60 * 1000\n\t\t\t\tthis.restartTimes = this.restartTimes.filter(\n\t\t\t\t\t(time) => time > fiveMinutesAgo,\n\t\t\t\t)\n\t\t\t\tthis.restartTimes.push(now)\n\n\t\t\t\tif (this.restartTimes.length < 5) {\n\t\t\t\t\tthis.serviceLoggers[serviceName].info(`Crashed. Restarting...`)\n\t\t\t\t\tthis.startService(serviceName)\n\t\t\t\t} else {\n\t\t\t\t\tthis.serviceLoggers[serviceName].info(\n\t\t\t\t\t\t`Crashed 5 times in 5 minutes. Not restarting.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t\tthis.safety = 0\n\t}\n\n\tprotected downloadPackage(): void {\n\t\tthis.logger.info(`Downloading...`)\n\t\ttry {\n\t\t\tconst out = execSync(this.options.scripts.download)\n\t\t\tthis.logger.info(`Download stdout:`, out.toString())\n\t\t\tthis.storage.setItem(`setupPhase`, `downloaded`)\n\t\t\tthis.logger.info(`Downloaded!`)\n\t\t} catch (thrown) {\n\t\t\tif (thrown instanceof Error) {\n\t\t\t\tthis.logger.error(`Failed to get the latest release: ${thrown.message}`)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\n\tprotected installPackage(): void {\n\t\tthis.logger.info(`Installing...`)\n\n\t\ttry {\n\t\t\tconst out = execSync(this.options.scripts.install)\n\t\t\tthis.logger.info(`Install stdout:`, out.toString())\n\t\t\tthis.storage.setItem(`setupPhase`, `installed`)\n\t\t\tthis.logger.info(`Installed!`)\n\t\t} catch (thrown) {\n\t\t\tif (thrown instanceof Error) {\n\t\t\t\tthis.logger.error(`Failed to get the latest release: ${thrown.message}`)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\n\tpublic stopAllServices(): Future<unknown> {\n\t\tthis.logger.info(`Stopping all services... auto-respawn disabled.`)\n\t\tthis.autoRespawnDeadServices = false\n\t\tfor (const [serviceName] of toEntries(this.services)) {\n\t\t\tthis.stopService(serviceName)\n\t\t}\n\t\treturn this.dead\n\t}\n\n\tpublic stopService(serviceName: S): void {\n\t\tconst service = this.services[serviceName]\n\t\tif (service) {\n\t\t\tthis.logger.info(`Stopping service \"${serviceName}\"...`)\n\t\t\tthis.servicesDead[this.serviceIdx[serviceName]].use(\n\t\t\t\tnew Promise((pass) => {\n\t\t\t\t\tservice.emit(`timeToStop`)\n\t\t\t\t\tservice.proc.once(`close`, (exitCode) => {\n\t\t\t\t\t\tthis.logger.info(\n\t\t\t\t\t\t\t`Stopped service \"${serviceName}\"; exited with code ${exitCode}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tthis.services[serviceName] = null\n\t\t\t\t\t\tpass()\n\t\t\t\t\t})\n\t\t\t\t}),\n\t\t\t)\n\t\t\tthis.dead.use(Promise.all(this.servicesDead))\n\t\t\tthis.servicesLive[this.serviceIdx[serviceName]] = new Future(() => {})\n\t\t\tif (this.live.done) {\n\t\t\t\tthis.live = new Future(() => {})\n\t\t\t}\n\t\t\tthis.live.use(Promise.all(this.servicesLive))\n\t\t} else {\n\t\t\tthis.serviceLoggers[serviceName].error(\n\t\t\t\t`Tried to stop service, but it wasn't running.`,\n\t\t\t)\n\t\t}\n\t}\n}\n\nexport const FLIGHTDECK_INFO = `info`\nexport const FLIGHTDECK_WARN = `warn`\nexport const FLIGHTDECK_ERROR = `ERR!`\n\nexport type FlightDeckLog = {\n\tlevel:\n\t\t| typeof FLIGHTDECK_ERROR\n\t\t| typeof FLIGHTDECK_INFO\n\t\t| typeof FLIGHTDECK_WARN\n\ttimestamp: number\n\tpackage: string\n\tservice?: string\n\tprocess: number\n\tbody: string\n}\n\nconst LINE_FORMAT = `line-format` satisfies keyof LnavFormat\nconst VALUE = `value` satisfies keyof LnavFormat\n\nexport type LnavFormatVisualComponent = Exclude<\n\tExclude<LnavFormat[`line-format`], undefined>[number],\n\tstring\n>\n\nexport type LnavFormatBreakdown = Exclude<LnavFormat[`value`], undefined>\nexport type MemberOf<T> = T[keyof T]\nexport type LnavFormatValueDefinition = MemberOf<LnavFormatBreakdown>\n\nexport type FlightDeckFormat = {\n\t[LINE_FORMAT]: (\n\t\t| string\n\t\t| (LnavFormatVisualComponent & {\n\t\t\t\tfield: keyof FlightDeckLog | `__level__` | `__timestamp__`\n\t\t })\n\t)[]\n\t[VALUE]: {\n\t\t[K in keyof FlightDeckLog]: LnavFormatValueDefinition & {\n\t\t\tkind: FlightDeckLog[K] extends number | undefined\n\t\t\t\t? `integer`\n\t\t\t\t: FlightDeckLog[K] extends string | undefined\n\t\t\t\t\t? `string`\n\t\t\t\t\t: never\n\t\t}\n\t}\n}\n\nexport const FLIGHTDECK_LNAV_FORMAT = {\n\ttitle: `FlightDeck Log`,\n\tdescription: `Format for events logged by the FlightDeck process manager.`,\n\t\"file-type\": `json`,\n\t\"timestamp-field\": `timestamp`,\n\t\"timestamp-divisor\": 1000,\n\t\"module-field\": `package`,\n\t\"opid-field\": `service`,\n\t\"level-field\": `level`,\n\tlevel: {\n\t\tinfo: FLIGHTDECK_INFO,\n\t\twarning: FLIGHTDECK_WARN,\n\t\terror: FLIGHTDECK_ERROR,\n\t},\n\n\t[LINE_FORMAT]: [\n\t\t{\n\t\t\tfield: `level`,\n\t\t},\n\t\t{\n\t\t\tprefix: ` `,\n\t\t\tfield: `__timestamp__`,\n\t\t\t\"timestamp-format\": `%Y-%m-%dT%H:%M:%S.%L%Z`,\n\t\t},\n\t\t{\n\t\t\tprefix: ` `,\n\t\t\tfield: `process`,\n\t\t\t\"min-width\": 5,\n\t\t},\n\t\t{\n\t\t\tprefix: `:`,\n\t\t\tfield: `package`,\n\t\t},\n\t\t{\n\t\t\tprefix: `:`,\n\t\t\tfield: `service`,\n\t\t\t\"default-value\": ``,\n\t\t},\n\t\t{\n\t\t\tprefix: `: `,\n\t\t\tfield: `body`,\n\t\t},\n\t],\n\n\t[VALUE]: {\n\t\ttimestamp: {\n\t\t\tkind: `integer`,\n\t\t},\n\t\tlevel: {\n\t\t\tkind: `string`,\n\t\t},\n\t\tpackage: {\n\t\t\tkind: `string`,\n\t\t},\n\t\tservice: {\n\t\t\tkind: `string`,\n\t\t},\n\t\tprocess: {\n\t\t\tkind: `integer`,\n\t\t},\n\t\tbody: {\n\t\t\tkind: `string`,\n\t\t},\n\t},\n} as const satisfies FlightDeckFormat & LnavFormat\n\nexport class FlightDeckLogger\n\timplements Pick<Console, `error` | `info` | `warn`>\n{\n\tpublic readonly packageName: string\n\tpublic readonly serviceName?: string\n\tpublic readonly jsonLogging: boolean\n\tpublic processCode: number\n\tpublic constructor(\n\t\tpackageName: string,\n\t\tprocessCode: number,\n\t\tserviceName?: string,\n\t\toptions?: { jsonLogging: boolean },\n\t) {\n\t\tthis.packageName = packageName\n\t\tif (serviceName) {\n\t\t\tthis.serviceName = serviceName\n\t\t}\n\t\tthis.processCode = processCode\n\t\tthis.jsonLogging = options?.jsonLogging ?? false\n\t}\n\tprotected log(\n\t\tlevel:\n\t\t\t| typeof FLIGHTDECK_ERROR\n\t\t\t| typeof FLIGHTDECK_INFO\n\t\t\t| typeof FLIGHTDECK_WARN,\n\t\t...messages: unknown[]\n\t): void {\n\t\tif (this.jsonLogging) {\n\t\t\tlet body = messages\n\t\t\t\t.map((message) =>\n\t\t\t\t\ttypeof message === `string`\n\t\t\t\t\t\t? message\n\t\t\t\t\t\t: inspect(message, false, null, true),\n\t\t\t\t)\n\t\t\t\t.join(` `)\n\t\t\tif (body.includes(`\\n`)) {\n\t\t\t\tbody = `\\n ${body.split(`\\n`).join(`\\n `)}`\n\t\t\t}\n\t\t\tconst log: FlightDeckLog = {\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel,\n\t\t\t\tprocess: this.processCode,\n\t\t\t\tpackage: this.packageName,\n\t\t\t\tbody,\n\t\t\t}\n\t\t\tif (this.serviceName) {\n\t\t\t\tlog.service = this.serviceName\n\t\t\t}\n\t\t\tprocess.stdout.write(JSON.stringify(log) + `\\n`)\n\t\t} else {\n\t\t\tconst source = this.serviceName\n\t\t\t\t? `${this.packageName}:${this.serviceName}`\n\t\t\t\t: this.packageName\n\t\t\tswitch (level) {\n\t\t\t\tcase FLIGHTDECK_INFO:\n\t\t\t\t\tconsole.log(`${source}:`, ...messages)\n\t\t\t\t\tbreak\n\t\t\t\tcase FLIGHTDECK_WARN:\n\t\t\t\t\tconsole.warn(`${source}:`, ...messages)\n\t\t\t\t\tbreak\n\t\t\t\tcase FLIGHTDECK_ERROR:\n\t\t\t\t\tconsole.error(`${source}:`, ...messages)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tpublic info(...messages: unknown[]): void {\n\t\tthis.log(FLIGHTDECK_INFO, ...messages)\n\t}\n\n\tpublic warn(...messages: unknown[]): void {\n\t\tthis.log(FLIGHTDECK_WARN, ...messages)\n\t}\n\n\tpublic error(...messages: unknown[]): void {\n\t\tthis.log(FLIGHTDECK_ERROR, ...messages)\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"flightdeck.lib-Dfs4xGO7.js","names":[],"sources":["../src/flightdeck.env.ts","../src/flightdeck.lib.ts"],"sourcesContent":["import { createEnv } from \"@t3-oss/env-core\"\nimport { type } from \"arktype\"\n\nexport const env = createEnv({\n\tserver: { FLIGHTDECK_SECRET: type(`string`, `|`, `undefined`) },\n\tclientPrefix: `NEVER`,\n\tclient: {},\n\truntimeEnv: import.meta.env,\n\temptyStringAsUndefined: true,\n})\n","/* oxlint-disable typescript/only-throw-error */\nimport type { ChildProcessWithoutNullStreams } from \"node:child_process\"\nimport { execSync, spawn } from \"node:child_process\"\nimport { createServer } from \"node:http\"\nimport { homedir } from \"node:os\"\nimport { resolve } from \"node:path\"\nimport { inspect } from \"node:util\"\n\nimport { Future } from \"atom.io/internal\"\nimport { discoverType } from \"atom.io/introspection\"\nimport { fromEntries, toEntries } from \"atom.io/json\"\nimport { ChildSocket } from \"atom.io/realtime-server\"\nimport { CronJob } from \"cron\"\nimport { FilesystemStorage } from \"safedeposit\"\n\nimport type { LnavFormat } from \"../gen/lnav-format-schema.gen.ts\"\nimport { env } from \"./flightdeck.env.ts\"\n\nexport const FLIGHTDECK_SETUP_PHASES = [`downloaded`, `installed`] as const\n\nexport type FlightDeckSetupPhase = (typeof FLIGHTDECK_SETUP_PHASES)[number]\n\nexport const FLIGHTDECK_UPDATE_PHASES = [`notified`, `confirmed`] as const\n\nexport type FlightDeckUpdatePhase = (typeof FLIGHTDECK_UPDATE_PHASES)[number]\n\nexport function isVersionNumber(version: string): boolean {\n\treturn (\n\t\t/^\\d+\\.\\d+\\.\\d+$/.test(version) || !Number.isNaN(Number.parseFloat(version))\n\t)\n}\n\nexport type FlightDeckSaveData = {\n\tcurrentPid: `${number}`\n\tsetupPhase: FlightDeckSetupPhase\n\tupdatePhase: FlightDeckUpdatePhase\n\tupdateAwaitedVersion: string\n}\n\nexport type FlightDeckOptions<S extends string = string> = {\n\treadonly packageName: string\n\treadonly services: { [service in S]: { run: string; waitFor: boolean } }\n\treadonly scripts: {\n\t\treadonly download: string\n\t\treadonly install: string\n\t\treadonly checkAvailability?: string\n\t}\n\treadonly port?: number | undefined\n\treadonly flightdeckRootDir?: string | undefined\n\treadonly jsonLogging?: boolean | undefined\n}\n\nasync function waitForPidExit(pid: number, timeoutMs = 5000, intervalMs = 100) {\n\treturn new Promise<void>((pass, fail) => {\n\t\tconst start = Date.now()\n\n\t\tconst check = () => {\n\t\t\tprocess.stdout.write(`.`)\n\t\t\ttry {\n\t\t\t\t// check existence\n\t\t\t\tprocess.kill(pid, 0)\n\t\t\t\t// process still alive\n\t\t\t\tif (Date.now() - start > timeoutMs) {\n\t\t\t\t\tfail(new Error(`Timeout waiting for PID ${pid}`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tsetTimeout(check, intervalMs)\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error && `code` in err) {\n\t\t\t\t\tif (err.code === `ESRCH`) {\n\t\t\t\t\t\tpass()\n\t\t\t\t\t\treturn // exited\n\t\t\t\t\t}\n\t\t\t\t\tif (err.code === `EPERM`) {\n\t\t\t\t\t\t// process is alive but protected\n\t\t\t\t\t\tif (Date.now() - start > timeoutMs) {\n\t\t\t\t\t\t\tfail(\n\t\t\t\t\t\t\t\tnew Error(`Timeout waiting for PID ${pid} (EPERM; still alive)`),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn setTimeout(check, intervalMs)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfail(err)\n\t\t\t\treturn // unexpected error\n\t\t\t}\n\t\t}\n\n\t\tcheck()\n\t})\n}\n\nexport class FlightDeck<S extends string = string> {\n\tpublic static async kill(\n\t\tflightdeckRootDir: string,\n\t\tpackageName: string,\n\t): Promise<number> {\n\t\tconsole.info(`Killing FlightDeck instance of \"${packageName}\"`)\n\t\tconst storage = new FilesystemStorage<FlightDeckSaveData>({\n\t\t\tpath: resolve(flightdeckRootDir, `storage`, packageName),\n\t\t})\n\t\tconst currentPid = storage.getItem(`currentPid`)\n\t\tif (currentPid === null) {\n\t\t\tthrow new Error(`No pid for \"${packageName}\" found in storage`)\n\t\t}\n\t\tconst pid = Number(currentPid)\n\t\tconst now = Date.now()\n\t\tprocess.kill(pid, `SIGTERM`)\n\t\tawait waitForPidExit(pid, 5000, 5)\n\t\tconst elapsed = Date.now() - now\n\t\tprocess.stdout.write(\n\t\t\t`🌜 \"${packageName}\" (running as process ${pid}) exited in ${elapsed}ms\\n`,\n\t\t)\n\t\treturn pid\n\t}\n\n\tpublic readonly options: FlightDeckOptions<S>\n\tprotected safety = 0\n\n\tprotected storage: FilesystemStorage<FlightDeckSaveData>\n\tprotected services: {\n\t\t[service in S]: ChildSocket<\n\t\t\t{ timeToStop: []; updatesReady: [] },\n\t\t\t{ readyToUpdate: []; alive: [] },\n\t\t\tChildProcessWithoutNullStreams\n\t\t> | null\n\t}\n\tprotected serviceIdx: { readonly [service in S]: number }\n\tpublic defaultServicesReadyToUpdate: { readonly [service in S]: boolean }\n\tpublic servicesReadyToUpdate: { [service in S]: boolean }\n\tpublic autoRespawnDeadServices: boolean\n\n\tprotected logger: Pick<Console, `error` | `info` | `warn`>\n\tprotected serviceLoggers: {\n\t\treadonly [service in S]: FlightDeckLogger\n\t}\n\n\tprotected updateAvailabilityChecker: CronJob | null = null\n\n\tpublic servicesLive: Future<void>[]\n\tpublic servicesDead: Future<void>[]\n\tpublic live = new Future(() => {})\n\tpublic dead = new Future(() => {})\n\n\tprotected restartTimes: number[] = []\n\n\tpublic constructor(options: FlightDeckOptions<S>) {\n\t\tthis.options = options\n\t\tconst { FLIGHTDECK_SECRET } = env\n\t\tconst { flightdeckRootDir = resolve(homedir(), `.flightdeck`) } = options\n\t\tconst port = options.port ?? 8080\n\t\tconst origin = `http://localhost:${port}`\n\n\t\tconst servicesEntries = toEntries(options.services)\n\t\tthis.services = fromEntries(\n\t\t\tservicesEntries.map(([serviceName]) => [serviceName, null]),\n\t\t)\n\t\tthis.serviceIdx = fromEntries(\n\t\t\tservicesEntries.map(([serviceName], idx) => [serviceName, idx]),\n\t\t)\n\t\tthis.defaultServicesReadyToUpdate = fromEntries(\n\t\t\tservicesEntries.map(([serviceName, { waitFor }]) => [\n\t\t\t\tserviceName,\n\t\t\t\t!waitFor,\n\t\t\t]),\n\t\t)\n\t\tthis.servicesReadyToUpdate = { ...this.defaultServicesReadyToUpdate }\n\t\tthis.autoRespawnDeadServices = true\n\n\t\tthis.logger = new FlightDeckLogger(\n\t\t\tthis.options.packageName,\n\t\t\tprocess.pid,\n\t\t\tundefined,\n\t\t\t{ jsonLogging: this.options.jsonLogging ?? false },\n\t\t)\n\t\tthis.serviceLoggers = fromEntries(\n\t\t\tservicesEntries.map(([serviceName]) => [\n\t\t\t\tserviceName,\n\t\t\t\tnew FlightDeckLogger(\n\t\t\t\t\tthis.options.packageName,\n\t\t\t\t\tprocess.pid,\n\t\t\t\t\tserviceName,\n\t\t\t\t\t{ jsonLogging: this.options.jsonLogging ?? false },\n\t\t\t\t),\n\t\t\t]),\n\t\t)\n\n\t\tthis.servicesLive = servicesEntries.map(() => new Future(() => {}))\n\t\tthis.servicesDead = servicesEntries.map(() => new Future(() => {}))\n\t\tthis.live.use(Promise.all(this.servicesLive))\n\t\tthis.dead.use(Promise.all(this.servicesDead))\n\n\t\tthis.storage = new FilesystemStorage({\n\t\t\tpath: resolve(flightdeckRootDir, `storage`, options.packageName),\n\t\t})\n\n\t\tthis.storage.setItem(`currentPid`, `${process.pid}`)\n\n\t\tif (FLIGHTDECK_SECRET === undefined) {\n\t\t\tthis.logger.warn(\n\t\t\t\t`No FLIGHTDECK_SECRET environment variable found. FlightDeck will not run an update server.`,\n\t\t\t)\n\t\t} else {\n\t\t\tcreateServer((req, res) => {\n\t\t\t\tlet data: Uint8Array[] = []\n\t\t\t\treq\n\t\t\t\t\t.on(`data`, (chunk) => {\n\t\t\t\t\t\tdata.push(chunk instanceof Buffer ? chunk : Buffer.from(chunk))\n\t\t\t\t\t})\n\t\t\t\t\t.on(`end`, async () => {\n\t\t\t\t\t\tconst authHeader = req.headers.authorization\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (typeof req.url === `undefined`) throw 400\n\t\t\t\t\t\t\tconst expectedAuthHeader = `Bearer ${FLIGHTDECK_SECRET}`\n\t\t\t\t\t\t\tif (authHeader !== `Bearer ${FLIGHTDECK_SECRET}`) {\n\t\t\t\t\t\t\t\tthis.logger.info(\n\t\t\t\t\t\t\t\t\t`Unauthorized: needed \\`${expectedAuthHeader}\\`, got \\`${authHeader}\\``,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tthrow 401\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst url = new URL(req.url, origin)\n\t\t\t\t\t\t\tthis.logger.info(req.method, url.pathname)\n\n\t\t\t\t\t\t\tconst versionForeignInput = Buffer.concat(data).toString()\n\t\t\t\t\t\t\tif (!isVersionNumber(versionForeignInput)) {\n\t\t\t\t\t\t\t\tthrow 400\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tres.writeHead(200)\n\t\t\t\t\t\t\tres.end()\n\n\t\t\t\t\t\t\tthis.storage.setItem(`updatePhase`, `notified`)\n\t\t\t\t\t\t\tthis.storage.setItem(`updateAwaitedVersion`, versionForeignInput)\n\t\t\t\t\t\t\tconst { checkAvailability } = options.scripts\n\t\t\t\t\t\t\tif (checkAvailability) {\n\t\t\t\t\t\t\t\tawait this.updateAvailabilityChecker?.stop()\n\t\t\t\t\t\t\t\tawait this.seekUpdate(versionForeignInput)\n\t\t\t\t\t\t\t\tconst updatePhase = this.storage.getItem(`updatePhase`)\n\t\t\t\t\t\t\t\tthis.logger.info(`> storage(\"updatePhase\") >`, updatePhase)\n\t\t\t\t\t\t\t\tif (updatePhase === `notified`) {\n\t\t\t\t\t\t\t\t\tthis.updateAvailabilityChecker = new CronJob(\n\t\t\t\t\t\t\t\t\t\t`*/30 * * * * *`,\n\t\t\t\t\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\t\t\t\t\tawait this.seekUpdate(versionForeignInput)\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tthis.updateAvailabilityChecker.start()\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.downloadPackage()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (thrown) {\n\t\t\t\t\t\t\tthis.logger.error(thrown, req.url)\n\t\t\t\t\t\t\tif (typeof thrown === `number`) {\n\t\t\t\t\t\t\t\tres.writeHead(thrown)\n\t\t\t\t\t\t\t\tres.end()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tdata = []\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t}).listen(port, () => {\n\t\t\t\tthis.logger.info(`Server started on port ${port}`)\n\t\t\t})\n\t\t}\n\n\t\tthis.startAllServices()\n\t\t\t.then(() => {\n\t\t\t\tthis.logger.info(`All services started.`)\n\t\t\t})\n\t\t\t.catch((thrown) => {\n\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\tthis.logger.error(`Failed to start all services:`, thrown.message)\n\t\t\t\t}\n\t\t\t})\n\n\t\tprocess.on(`SIGTERM`, async () => {\n\t\t\tconsole.info(`Killed by SIGTERM`)\n\t\t\tawait this.stopAllServices()\n\t\t\tthis.storage.removeItem(`currentPid`)\n\t\t\tprocess.exit(0)\n\t\t})\n\t}\n\n\tprotected async seekUpdate(version: string): Promise<void> {\n\t\tthis.logger.info(`Checking for updates...`)\n\t\tconst { checkAvailability } = this.options.scripts\n\t\tif (!checkAvailability) {\n\t\t\tthis.logger.info(`No checkAvailability script found.`)\n\t\t\treturn\n\t\t}\n\t\ttry {\n\t\t\tconst out = execSync(`${checkAvailability} ${version}`)\n\t\t\tthis.logger.info(`Check stdout:`, out.toString())\n\t\t\tawait this.updateAvailabilityChecker?.stop()\n\t\t\tthis.storage.setItem(`updatePhase`, `confirmed`)\n\t\t\tthis.downloadPackage()\n\t\t\tthis.announceUpdate()\n\t\t} catch (thrown) {\n\t\t\tif (thrown instanceof Error) {\n\t\t\t\tthis.logger.error(`Check failed:`, thrown.message)\n\t\t\t} else {\n\t\t\t\tconst thrownType = discoverType(thrown)\n\t\t\t\tthis.logger.error(`Check threw`, thrownType, thrown)\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected announceUpdate(): void {\n\t\tfor (const entry of toEntries(this.services)) {\n\t\t\tconst [serviceName, service] = entry\n\t\t\tif (service) {\n\t\t\t\tif (this.options.services[serviceName].waitFor) {\n\t\t\t\t\tservice.emit(`updatesReady`)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.startService(serviceName)\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected tryUpdate(): void {\n\t\tif (toEntries(this.servicesReadyToUpdate).every(([, isReady]) => isReady)) {\n\t\t\tthis.logger.info(`All services are ready to update.`)\n\t\t\tthis.stopAllServices()\n\t\t\t\t.then(() => {\n\t\t\t\t\tthis.logger.info(`All services stopped; starting up fresh...`)\n\t\t\t\t\tthis.startAllServices()\n\t\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t\tthis.logger.info(`All services started; we're back online.`)\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch((thrown) => {\n\t\t\t\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t\t\t`Failed to start all services:`,\n\t\t\t\t\t\t\t\t\tthrown.message,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t\t.catch((thrown) => {\n\t\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\t\tthis.logger.error(`Failed to stop all services:`, thrown.message)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t}\n\t}\n\n\tprotected startAllServices(): Future<unknown> {\n\t\tthis.logger.info(`Starting all services...`)\n\t\tthis.autoRespawnDeadServices = true\n\t\tconst setupPhase = this.storage.getItem(`setupPhase`)\n\t\tthis.logger.info(`> storage(\"setupPhase\") >`, setupPhase)\n\t\tswitch (setupPhase) {\n\t\t\tcase null:\n\t\t\t\tthis.logger.info(`Starting from scratch.`)\n\t\t\t\tthis.downloadPackage()\n\t\t\t\tthis.installPackage()\n\t\t\t\treturn this.startAllServices()\n\t\t\tcase `downloaded`:\n\t\t\t\tthis.logger.info(`Found package downloaded but not installed.`)\n\t\t\t\tthis.installPackage()\n\t\t\t\treturn this.startAllServices()\n\t\t\tcase `installed`: {\n\t\t\t\tfor (const [serviceName] of toEntries(this.services)) {\n\t\t\t\t\tthis.startService(serviceName)\n\t\t\t\t}\n\t\t\t\treturn this.live\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected startService(serviceName: S): void {\n\t\tthis.logger.info(\n\t\t\t`Starting service ${this.options.packageName}::${serviceName}, try ${this.safety}/2...`,\n\t\t)\n\t\tif (this.safety >= 2) {\n\t\t\tthrow new Error(`Out of tries...`)\n\t\t}\n\t\tthis.safety++\n\n\t\tconst [exe, ...args] = this.options.services[serviceName].run.split(` `)\n\t\tconst serviceProcess = spawn(exe, args, {\n\t\t\tcwd: this.options.flightdeckRootDir,\n\t\t\tenv: import.meta.env,\n\t\t})\n\t\tconst serviceLogger = this.serviceLoggers[serviceName]\n\t\tconst service = (this.services[serviceName] = new ChildSocket(\n\t\t\tserviceProcess,\n\t\t\t`${this.options.packageName}::${serviceName}`,\n\t\t\tserviceLogger,\n\t\t))\n\t\tserviceLogger.processCode = service.proc.pid ?? -1\n\t\tthis.services[serviceName].onAny((...messages) => {\n\t\t\tserviceLogger.info(`💬`, ...messages)\n\t\t})\n\t\tthis.services[serviceName].on(`readyToUpdate`, () => {\n\t\t\tthis.logger.info(`Service \"${serviceName}\" is ready to update.`)\n\t\t\tthis.servicesReadyToUpdate[serviceName] = true\n\t\t\tthis.tryUpdate()\n\t\t})\n\t\tthis.services[serviceName].on(`alive`, () => {\n\t\t\tthis.servicesLive[this.serviceIdx[serviceName]].use(Promise.resolve())\n\t\t\tthis.servicesDead[this.serviceIdx[serviceName]] = new Future(() => {})\n\t\t\tif (this.dead.done) {\n\t\t\t\tthis.dead = new Future(() => {})\n\t\t\t}\n\t\t\tthis.dead.use(Promise.all(this.servicesDead))\n\t\t})\n\t\tthis.services[serviceName].proc.once(`close`, (exitCode) => {\n\t\t\tthis.logger.info(\n\t\t\t\t`Auto-respawn saw \"${serviceName}\" exit with code ${exitCode}`,\n\t\t\t)\n\t\t\tthis.services[serviceName] = null\n\t\t\tif (!this.autoRespawnDeadServices) {\n\t\t\t\tthis.logger.info(`😴 Auto-respawn is off; \"${serviceName}\" rests.`)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst updatePhase = this.storage.getItem(`updatePhase`)\n\t\t\tthis.logger.info(`> storage(\"updatePhase\") >`, updatePhase)\n\t\t\tconst updatesAreReady = updatePhase === `confirmed`\n\t\t\tif (updatesAreReady) {\n\t\t\t\tthis.serviceLoggers[serviceName].info(`Updating before startup...`)\n\t\t\t\tthis.restartTimes = []\n\t\t\t\tthis.installPackage()\n\t\t\t\tthis.startService(serviceName)\n\t\t\t} else {\n\t\t\t\tconst now = Date.now()\n\t\t\t\tconst fiveMinutesAgo = now - 5 * 60 * 1000\n\t\t\t\tthis.restartTimes = this.restartTimes.filter(\n\t\t\t\t\t(time) => time > fiveMinutesAgo,\n\t\t\t\t)\n\t\t\t\tthis.restartTimes.push(now)\n\n\t\t\t\tif (this.restartTimes.length < 5) {\n\t\t\t\t\tthis.serviceLoggers[serviceName].info(`Crashed. Restarting...`)\n\t\t\t\t\tthis.startService(serviceName)\n\t\t\t\t} else {\n\t\t\t\t\tthis.serviceLoggers[serviceName].info(\n\t\t\t\t\t\t`Crashed 5 times in 5 minutes. Not restarting.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t\tthis.safety = 0\n\t}\n\n\tprotected downloadPackage(): void {\n\t\tthis.logger.info(`Downloading...`)\n\t\ttry {\n\t\t\tconst out = execSync(this.options.scripts.download)\n\t\t\tthis.logger.info(`Download stdout:`, out.toString())\n\t\t\tthis.storage.setItem(`setupPhase`, `downloaded`)\n\t\t\tthis.logger.info(`Downloaded!`)\n\t\t} catch (thrown) {\n\t\t\tif (thrown instanceof Error) {\n\t\t\t\tthis.logger.error(`Failed to get the latest release: ${thrown.message}`)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\n\tprotected installPackage(): void {\n\t\tthis.logger.info(`Installing...`)\n\n\t\ttry {\n\t\t\tconst out = execSync(this.options.scripts.install)\n\t\t\tthis.logger.info(`Install stdout:`, out.toString())\n\t\t\tthis.storage.setItem(`setupPhase`, `installed`)\n\t\t\tthis.logger.info(`Installed!`)\n\t\t} catch (thrown) {\n\t\t\tif (thrown instanceof Error) {\n\t\t\t\tthis.logger.error(`Failed to get the latest release: ${thrown.message}`)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\n\tpublic stopAllServices(): Future<unknown> {\n\t\tthis.logger.info(`Stopping all services... auto-respawn disabled.`)\n\t\tthis.autoRespawnDeadServices = false\n\t\tfor (const [serviceName] of toEntries(this.services)) {\n\t\t\tthis.stopService(serviceName)\n\t\t}\n\t\treturn this.dead\n\t}\n\n\tpublic stopService(serviceName: S): void {\n\t\tconst service = this.services[serviceName]\n\t\tif (service) {\n\t\t\tthis.logger.info(`Stopping service \"${serviceName}\"...`)\n\t\t\tthis.servicesDead[this.serviceIdx[serviceName]].use(\n\t\t\t\tnew Promise((pass) => {\n\t\t\t\t\tservice.emit(`timeToStop`)\n\t\t\t\t\tservice.proc.once(`close`, (exitCode) => {\n\t\t\t\t\t\tthis.logger.info(\n\t\t\t\t\t\t\t`Stopped service \"${serviceName}\"; exited with code ${exitCode}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tthis.services[serviceName] = null\n\t\t\t\t\t\tpass()\n\t\t\t\t\t})\n\t\t\t\t}),\n\t\t\t)\n\t\t\tthis.dead.use(Promise.all(this.servicesDead))\n\t\t\tthis.servicesLive[this.serviceIdx[serviceName]] = new Future(() => {})\n\t\t\tif (this.live.done) {\n\t\t\t\tthis.live = new Future(() => {})\n\t\t\t}\n\t\t\tthis.live.use(Promise.all(this.servicesLive))\n\t\t} else {\n\t\t\tthis.serviceLoggers[serviceName].error(\n\t\t\t\t`Tried to stop service, but it wasn't running.`,\n\t\t\t)\n\t\t}\n\t}\n}\n\nexport const FLIGHTDECK_INFO = `info`\nexport const FLIGHTDECK_WARN = `warn`\nexport const FLIGHTDECK_ERROR = `ERR!`\n\nexport type FlightDeckLog = {\n\tlevel:\n\t\t| typeof FLIGHTDECK_ERROR\n\t\t| typeof FLIGHTDECK_INFO\n\t\t| typeof FLIGHTDECK_WARN\n\ttimestamp: number\n\tpackage: string\n\tservice?: string\n\tprocess: number\n\tbody: string\n}\n\nconst LINE_FORMAT = `line-format` satisfies keyof LnavFormat\nconst VALUE = `value` satisfies keyof LnavFormat\n\nexport type LnavFormatVisualComponent = Exclude<\n\tExclude<LnavFormat[`line-format`], undefined>[number],\n\tstring\n>\n\nexport type LnavFormatBreakdown = Exclude<LnavFormat[`value`], undefined>\nexport type MemberOf<T> = T[keyof T]\nexport type LnavFormatValueDefinition = MemberOf<LnavFormatBreakdown>\n\nexport type FlightDeckFormat = {\n\t[LINE_FORMAT]: (\n\t\t| string\n\t\t| (LnavFormatVisualComponent & {\n\t\t\t\tfield: keyof FlightDeckLog | `__level__` | `__timestamp__`\n\t\t })\n\t)[]\n\t[VALUE]: {\n\t\t[K in keyof FlightDeckLog]: LnavFormatValueDefinition & {\n\t\t\tkind: FlightDeckLog[K] extends number | undefined\n\t\t\t\t? `integer`\n\t\t\t\t: FlightDeckLog[K] extends string | undefined\n\t\t\t\t\t? `string`\n\t\t\t\t\t: never\n\t\t}\n\t}\n}\n\nexport const FLIGHTDECK_LNAV_FORMAT = {\n\ttitle: `FlightDeck Log`,\n\tdescription: `Format for events logged by the FlightDeck process manager.`,\n\t\"file-type\": `json`,\n\t\"timestamp-field\": `timestamp`,\n\t\"timestamp-divisor\": 1000,\n\t\"module-field\": `package`,\n\t\"opid-field\": `service`,\n\t\"level-field\": `level`,\n\tlevel: {\n\t\tinfo: FLIGHTDECK_INFO,\n\t\twarning: FLIGHTDECK_WARN,\n\t\terror: FLIGHTDECK_ERROR,\n\t},\n\n\t[LINE_FORMAT]: [\n\t\t{\n\t\t\tfield: `level`,\n\t\t},\n\t\t{\n\t\t\tprefix: ` `,\n\t\t\tfield: `__timestamp__`,\n\t\t\t\"timestamp-format\": `%Y-%m-%dT%H:%M:%S.%L%Z`,\n\t\t},\n\t\t{\n\t\t\tprefix: ` `,\n\t\t\tfield: `process`,\n\t\t\t\"min-width\": 5,\n\t\t},\n\t\t{\n\t\t\tprefix: `:`,\n\t\t\tfield: `package`,\n\t\t},\n\t\t{\n\t\t\tprefix: `:`,\n\t\t\tfield: `service`,\n\t\t\t\"default-value\": ``,\n\t\t},\n\t\t{\n\t\t\tprefix: `: `,\n\t\t\tfield: `body`,\n\t\t},\n\t],\n\n\t[VALUE]: {\n\t\ttimestamp: {\n\t\t\tkind: `integer`,\n\t\t},\n\t\tlevel: {\n\t\t\tkind: `string`,\n\t\t},\n\t\tpackage: {\n\t\t\tkind: `string`,\n\t\t},\n\t\tservice: {\n\t\t\tkind: `string`,\n\t\t},\n\t\tprocess: {\n\t\t\tkind: `integer`,\n\t\t},\n\t\tbody: {\n\t\t\tkind: `string`,\n\t\t},\n\t},\n} as const satisfies FlightDeckFormat & LnavFormat\n\nexport class FlightDeckLogger implements Pick<\n\tConsole,\n\t`error` | `info` | `warn`\n> {\n\tpublic readonly packageName: string\n\tpublic readonly serviceName?: string\n\tpublic readonly jsonLogging: boolean\n\tpublic processCode: number\n\tpublic constructor(\n\t\tpackageName: string,\n\t\tprocessCode: number,\n\t\tserviceName?: string,\n\t\toptions?: { jsonLogging: boolean },\n\t) {\n\t\tthis.packageName = packageName\n\t\tif (serviceName) {\n\t\t\tthis.serviceName = serviceName\n\t\t}\n\t\tthis.processCode = processCode\n\t\tthis.jsonLogging = options?.jsonLogging ?? false\n\t}\n\tprotected log(\n\t\tlevel:\n\t\t\t| typeof FLIGHTDECK_ERROR\n\t\t\t| typeof FLIGHTDECK_INFO\n\t\t\t| typeof FLIGHTDECK_WARN,\n\t\t...messages: unknown[]\n\t): void {\n\t\tif (this.jsonLogging) {\n\t\t\tlet body = messages\n\t\t\t\t.map((message) =>\n\t\t\t\t\ttypeof message === `string`\n\t\t\t\t\t\t? message\n\t\t\t\t\t\t: inspect(message, false, null, true),\n\t\t\t\t)\n\t\t\t\t.join(` `)\n\t\t\tif (body.includes(`\\n`)) {\n\t\t\t\tbody = `\\n ${body.split(`\\n`).join(`\\n `)}`\n\t\t\t}\n\t\t\tconst log: FlightDeckLog = {\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel,\n\t\t\t\tprocess: this.processCode,\n\t\t\t\tpackage: this.packageName,\n\t\t\t\tbody,\n\t\t\t}\n\t\t\tif (this.serviceName) {\n\t\t\t\tlog.service = this.serviceName\n\t\t\t}\n\t\t\tprocess.stdout.write(JSON.stringify(log) + `\\n`)\n\t\t} else {\n\t\t\tconst source = this.serviceName\n\t\t\t\t? `${this.packageName}:${this.serviceName}`\n\t\t\t\t: this.packageName\n\t\t\tswitch (level) {\n\t\t\t\tcase FLIGHTDECK_INFO:\n\t\t\t\t\tconsole.log(`${source}:`, ...messages)\n\t\t\t\t\tbreak\n\t\t\t\tcase FLIGHTDECK_WARN:\n\t\t\t\t\tconsole.warn(`${source}:`, ...messages)\n\t\t\t\t\tbreak\n\t\t\t\tcase FLIGHTDECK_ERROR:\n\t\t\t\t\tconsole.error(`${source}:`, ...messages)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tpublic info(...messages: unknown[]): void {\n\t\tthis.log(FLIGHTDECK_INFO, ...messages)\n\t}\n\n\tpublic warn(...messages: unknown[]): void {\n\t\tthis.log(FLIGHTDECK_WARN, ...messages)\n\t}\n\n\tpublic error(...messages: unknown[]): void {\n\t\tthis.log(FLIGHTDECK_ERROR, ...messages)\n\t}\n}\n"],"mappings":"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"}
|
package/dist/lib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","names":[],"sources":["../gen/lnav-format-schema.gen.ts","../src/flightdeck.lib.ts","../src/klaxon.lib.ts"],"mappings":";;;;;;;;cAEa,gBAAA,EAAgB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"lib.d.ts","names":[],"sources":["../gen/lnav-format-schema.gen.ts","../src/flightdeck.lib.ts","../src/klaxon.lib.ts"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { z } from "zod"
|
|
1
|
+
import { z } from "zod"
|
|
2
2
|
|
|
3
3
|
export const lnavFormatSchema = z
|
|
4
4
|
.object({
|
|
@@ -29,9 +29,9 @@ export const lnavFormatSchema = z
|
|
|
29
29
|
)
|
|
30
30
|
.superRefine((value, ctx) => {
|
|
31
31
|
for (const key in value) {
|
|
32
|
-
let evaluated = false
|
|
33
|
-
if (key.match(
|
|
34
|
-
evaluated = true
|
|
32
|
+
let evaluated = false
|
|
33
|
+
if (key.match(new RegExp("^(.+)$"))) {
|
|
34
|
+
evaluated = true
|
|
35
35
|
const result = z
|
|
36
36
|
.object({
|
|
37
37
|
pattern: z
|
|
@@ -50,7 +50,7 @@ export const lnavFormatSchema = z
|
|
|
50
50
|
})
|
|
51
51
|
.strict()
|
|
52
52
|
.describe("The set of patterns used to match log messages")
|
|
53
|
-
.safeParse(value[key])
|
|
53
|
+
.safeParse(value[key])
|
|
54
54
|
if (!result.success) {
|
|
55
55
|
ctx.addIssue({
|
|
56
56
|
path: [key],
|
|
@@ -59,11 +59,11 @@ export const lnavFormatSchema = z
|
|
|
59
59
|
params: {
|
|
60
60
|
issues: result.error.issues,
|
|
61
61
|
},
|
|
62
|
-
})
|
|
62
|
+
})
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
if (!evaluated) {
|
|
66
|
-
const result = z.never().safeParse(value[key])
|
|
66
|
+
const result = z.never().safeParse(value[key])
|
|
67
67
|
if (!result.success) {
|
|
68
68
|
ctx.addIssue({
|
|
69
69
|
path: [key],
|
|
@@ -72,7 +72,7 @@ export const lnavFormatSchema = z
|
|
|
72
72
|
params: {
|
|
73
73
|
issues: result.error.issues,
|
|
74
74
|
},
|
|
75
|
-
})
|
|
75
|
+
})
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -106,14 +106,10 @@ export const lnavFormatSchema = z
|
|
|
106
106
|
z
|
|
107
107
|
.number()
|
|
108
108
|
.int()
|
|
109
|
-
.describe(
|
|
110
|
-
"The value to divide a numeric timestamp by in a JSON log.",
|
|
111
|
-
),
|
|
109
|
+
.describe("The value to divide a numeric timestamp by in a JSON log."),
|
|
112
110
|
z
|
|
113
111
|
.number()
|
|
114
|
-
.describe(
|
|
115
|
-
"The value to divide a numeric timestamp by in a JSON log.",
|
|
116
|
-
),
|
|
112
|
+
.describe("The value to divide a numeric timestamp by in a JSON log."),
|
|
117
113
|
])
|
|
118
114
|
.describe("The value to divide a numeric timestamp by in a JSON log.")
|
|
119
115
|
.optional(),
|
|
@@ -135,13 +131,13 @@ export const lnavFormatSchema = z
|
|
|
135
131
|
)
|
|
136
132
|
.superRefine((value, ctx) => {
|
|
137
133
|
for (const key in value) {
|
|
138
|
-
let evaluated = false
|
|
139
|
-
if (key.match(
|
|
140
|
-
evaluated = true
|
|
134
|
+
let evaluated = false
|
|
135
|
+
if (key.match(new RegExp("^(\\w+)$"))) {
|
|
136
|
+
evaluated = true
|
|
141
137
|
const result = z
|
|
142
138
|
.string()
|
|
143
139
|
.describe("SQLite expression")
|
|
144
|
-
.safeParse(value[key])
|
|
140
|
+
.safeParse(value[key])
|
|
145
141
|
if (!result.success) {
|
|
146
142
|
ctx.addIssue({
|
|
147
143
|
path: [key],
|
|
@@ -150,11 +146,11 @@ export const lnavFormatSchema = z
|
|
|
150
146
|
params: {
|
|
151
147
|
issues: result.error.issues,
|
|
152
148
|
},
|
|
153
|
-
})
|
|
149
|
+
})
|
|
154
150
|
}
|
|
155
151
|
}
|
|
156
152
|
if (!evaluated) {
|
|
157
|
-
const result = z.never().safeParse(value[key])
|
|
153
|
+
const result = z.never().safeParse(value[key])
|
|
158
154
|
if (!result.success) {
|
|
159
155
|
ctx.addIssue({
|
|
160
156
|
path: [key],
|
|
@@ -163,7 +159,7 @@ export const lnavFormatSchema = z
|
|
|
163
159
|
params: {
|
|
164
160
|
issues: result.error.issues,
|
|
165
161
|
},
|
|
166
|
-
})
|
|
162
|
+
})
|
|
167
163
|
}
|
|
168
164
|
}
|
|
169
165
|
}
|
|
@@ -183,7 +179,7 @@ export const lnavFormatSchema = z
|
|
|
183
179
|
.optional(),
|
|
184
180
|
command: z
|
|
185
181
|
.string()
|
|
186
|
-
.regex(
|
|
182
|
+
.regex(new RegExp("[\\w\\.\\-]+"))
|
|
187
183
|
.describe("The script used to convert the file")
|
|
188
184
|
.optional(),
|
|
189
185
|
})
|
|
@@ -231,9 +227,7 @@ export const lnavFormatSchema = z
|
|
|
231
227
|
z
|
|
232
228
|
.array(z.string())
|
|
233
229
|
.describe("A URL with more information about this log format"),
|
|
234
|
-
z
|
|
235
|
-
.string()
|
|
236
|
-
.describe("A URL with more information about this log format"),
|
|
230
|
+
z.string().describe("A URL with more information about this log format"),
|
|
237
231
|
])
|
|
238
232
|
.describe("A URL with more information about this log format")
|
|
239
233
|
.optional(),
|
|
@@ -318,9 +312,9 @@ export const lnavFormatSchema = z
|
|
|
318
312
|
)
|
|
319
313
|
.superRefine((value, ctx) => {
|
|
320
314
|
for (const key in value) {
|
|
321
|
-
let evaluated = false
|
|
322
|
-
if (key.match(
|
|
323
|
-
evaluated = true
|
|
315
|
+
let evaluated = false
|
|
316
|
+
if (key.match(new RegExp("^([\\w\\.\\-]+)$"))) {
|
|
317
|
+
evaluated = true
|
|
324
318
|
const result = z
|
|
325
319
|
.object({
|
|
326
320
|
format: z
|
|
@@ -367,7 +361,7 @@ export const lnavFormatSchema = z
|
|
|
367
361
|
})
|
|
368
362
|
.strict()
|
|
369
363
|
.describe("A type of description for this operation")
|
|
370
|
-
.safeParse(value[key])
|
|
364
|
+
.safeParse(value[key])
|
|
371
365
|
if (!result.success) {
|
|
372
366
|
ctx.addIssue({
|
|
373
367
|
path: [key],
|
|
@@ -376,11 +370,11 @@ export const lnavFormatSchema = z
|
|
|
376
370
|
params: {
|
|
377
371
|
issues: result.error.issues,
|
|
378
372
|
},
|
|
379
|
-
})
|
|
373
|
+
})
|
|
380
374
|
}
|
|
381
375
|
}
|
|
382
376
|
if (!evaluated) {
|
|
383
|
-
const result = z.never().safeParse(value[key])
|
|
377
|
+
const result = z.never().safeParse(value[key])
|
|
384
378
|
if (!result.success) {
|
|
385
379
|
ctx.addIssue({
|
|
386
380
|
path: [key],
|
|
@@ -389,7 +383,7 @@ export const lnavFormatSchema = z
|
|
|
389
383
|
params: {
|
|
390
384
|
issues: result.error.issues,
|
|
391
385
|
},
|
|
392
|
-
})
|
|
386
|
+
})
|
|
393
387
|
}
|
|
394
388
|
}
|
|
395
389
|
}
|
|
@@ -451,9 +445,9 @@ export const lnavFormatSchema = z
|
|
|
451
445
|
)
|
|
452
446
|
.superRefine((value, ctx) => {
|
|
453
447
|
for (const key in value) {
|
|
454
|
-
let evaluated = false
|
|
455
|
-
if (key.match(
|
|
456
|
-
evaluated = true
|
|
448
|
+
let evaluated = false
|
|
449
|
+
if (key.match(new RegExp("^([\\w\\.\\-]+)$"))) {
|
|
450
|
+
evaluated = true
|
|
457
451
|
const result = z
|
|
458
452
|
.object({
|
|
459
453
|
format: z
|
|
@@ -500,7 +494,7 @@ export const lnavFormatSchema = z
|
|
|
500
494
|
})
|
|
501
495
|
.strict()
|
|
502
496
|
.describe("A type of description for this sub-operation")
|
|
503
|
-
.safeParse(value[key])
|
|
497
|
+
.safeParse(value[key])
|
|
504
498
|
if (!result.success) {
|
|
505
499
|
ctx.addIssue({
|
|
506
500
|
path: [key],
|
|
@@ -509,11 +503,11 @@ export const lnavFormatSchema = z
|
|
|
509
503
|
params: {
|
|
510
504
|
issues: result.error.issues,
|
|
511
505
|
},
|
|
512
|
-
})
|
|
506
|
+
})
|
|
513
507
|
}
|
|
514
508
|
}
|
|
515
509
|
if (!evaluated) {
|
|
516
|
-
const result = z.never().safeParse(value[key])
|
|
510
|
+
const result = z.never().safeParse(value[key])
|
|
517
511
|
if (!result.success) {
|
|
518
512
|
ctx.addIssue({
|
|
519
513
|
path: [key],
|
|
@@ -522,7 +516,7 @@ export const lnavFormatSchema = z
|
|
|
522
516
|
params: {
|
|
523
517
|
issues: result.error.issues,
|
|
524
518
|
},
|
|
525
|
-
})
|
|
519
|
+
})
|
|
526
520
|
}
|
|
527
521
|
}
|
|
528
522
|
}
|
|
@@ -565,13 +559,15 @@ export const lnavFormatSchema = z
|
|
|
565
559
|
)
|
|
566
560
|
.superRefine((value, ctx) => {
|
|
567
561
|
for (const key in value) {
|
|
568
|
-
let evaluated = false
|
|
562
|
+
let evaluated = false
|
|
569
563
|
if (
|
|
570
564
|
key.match(
|
|
571
|
-
|
|
565
|
+
new RegExp(
|
|
566
|
+
"^(trace|debug[2345]?|info|stats|notice|warning|error|critical|fatal)$",
|
|
567
|
+
),
|
|
572
568
|
)
|
|
573
569
|
) {
|
|
574
|
-
evaluated = true
|
|
570
|
+
evaluated = true
|
|
575
571
|
const result = z
|
|
576
572
|
.union([
|
|
577
573
|
z
|
|
@@ -589,7 +585,7 @@ export const lnavFormatSchema = z
|
|
|
589
585
|
.describe(
|
|
590
586
|
"The regular expression used to match the log text for this level. For JSON logs with numeric levels, this should be the number for the corresponding level.",
|
|
591
587
|
)
|
|
592
|
-
.safeParse(value[key])
|
|
588
|
+
.safeParse(value[key])
|
|
593
589
|
if (!result.success) {
|
|
594
590
|
ctx.addIssue({
|
|
595
591
|
path: [key],
|
|
@@ -598,11 +594,11 @@ export const lnavFormatSchema = z
|
|
|
598
594
|
params: {
|
|
599
595
|
issues: result.error.issues,
|
|
600
596
|
},
|
|
601
|
-
})
|
|
597
|
+
})
|
|
602
598
|
}
|
|
603
599
|
}
|
|
604
600
|
if (!evaluated) {
|
|
605
|
-
const result = z.never().safeParse(value[key])
|
|
601
|
+
const result = z.never().safeParse(value[key])
|
|
606
602
|
if (!result.success) {
|
|
607
603
|
ctx.addIssue({
|
|
608
604
|
path: [key],
|
|
@@ -611,7 +607,7 @@ export const lnavFormatSchema = z
|
|
|
611
607
|
params: {
|
|
612
608
|
issues: result.error.issues,
|
|
613
609
|
},
|
|
614
|
-
})
|
|
610
|
+
})
|
|
615
611
|
}
|
|
616
612
|
}
|
|
617
613
|
}
|
|
@@ -666,9 +662,9 @@ export const lnavFormatSchema = z
|
|
|
666
662
|
)
|
|
667
663
|
.superRefine((value, ctx) => {
|
|
668
664
|
for (const key in value) {
|
|
669
|
-
let evaluated = false
|
|
670
|
-
if (key.match(
|
|
671
|
-
evaluated = true
|
|
665
|
+
let evaluated = false
|
|
666
|
+
if (key.match(new RegExp("^(.+)$"))) {
|
|
667
|
+
evaluated = true
|
|
672
668
|
const result = z
|
|
673
669
|
.object({
|
|
674
670
|
op: z
|
|
@@ -677,7 +673,7 @@ export const lnavFormatSchema = z
|
|
|
677
673
|
value: z.number().optional(),
|
|
678
674
|
})
|
|
679
675
|
.strict()
|
|
680
|
-
.safeParse(value[key])
|
|
676
|
+
.safeParse(value[key])
|
|
681
677
|
if (!result.success) {
|
|
682
678
|
ctx.addIssue({
|
|
683
679
|
path: [key],
|
|
@@ -686,11 +682,11 @@ export const lnavFormatSchema = z
|
|
|
686
682
|
params: {
|
|
687
683
|
issues: result.error.issues,
|
|
688
684
|
},
|
|
689
|
-
})
|
|
685
|
+
})
|
|
690
686
|
}
|
|
691
687
|
}
|
|
692
688
|
if (!evaluated) {
|
|
693
|
-
const result = z.never().safeParse(value[key])
|
|
689
|
+
const result = z.never().safeParse(value[key])
|
|
694
690
|
if (!result.success) {
|
|
695
691
|
ctx.addIssue({
|
|
696
692
|
path: [key],
|
|
@@ -699,14 +695,12 @@ export const lnavFormatSchema = z
|
|
|
699
695
|
params: {
|
|
700
696
|
issues: result.error.issues,
|
|
701
697
|
},
|
|
702
|
-
})
|
|
698
|
+
})
|
|
703
699
|
}
|
|
704
700
|
}
|
|
705
701
|
}
|
|
706
702
|
})
|
|
707
|
-
.describe(
|
|
708
|
-
"Transforms the numeric value by the given factor",
|
|
709
|
-
)
|
|
703
|
+
.describe("Transforms the numeric value by the given factor")
|
|
710
704
|
.optional(),
|
|
711
705
|
})
|
|
712
706
|
.strict()
|
|
@@ -726,9 +720,7 @@ export const lnavFormatSchema = z
|
|
|
726
720
|
.optional(),
|
|
727
721
|
hidden: z
|
|
728
722
|
.boolean()
|
|
729
|
-
.describe(
|
|
730
|
-
"Indicates whether or not this field should be hidden",
|
|
731
|
-
)
|
|
723
|
+
.describe("Indicates whether or not this field should be hidden")
|
|
732
724
|
.optional(),
|
|
733
725
|
"action-list": z
|
|
734
726
|
.array(z.string())
|
|
@@ -752,9 +744,9 @@ export const lnavFormatSchema = z
|
|
|
752
744
|
)
|
|
753
745
|
.superRefine((value, ctx) => {
|
|
754
746
|
for (const key in value) {
|
|
755
|
-
let evaluated = false
|
|
756
|
-
if (key.match(
|
|
757
|
-
evaluated = true
|
|
747
|
+
let evaluated = false
|
|
748
|
+
if (key.match(new RegExp("^(.+)$"))) {
|
|
749
|
+
evaluated = true
|
|
758
750
|
const result = z
|
|
759
751
|
.object({
|
|
760
752
|
kind: z
|
|
@@ -799,9 +791,9 @@ export const lnavFormatSchema = z
|
|
|
799
791
|
)
|
|
800
792
|
.superRefine((value, ctx) => {
|
|
801
793
|
for (const key in value) {
|
|
802
|
-
let evaluated = false
|
|
803
|
-
if (key.match(
|
|
804
|
-
evaluated = true
|
|
794
|
+
let evaluated = false
|
|
795
|
+
if (key.match(new RegExp("^(.+)$"))) {
|
|
796
|
+
evaluated = true
|
|
805
797
|
const result = z
|
|
806
798
|
.object({
|
|
807
799
|
op: z
|
|
@@ -810,7 +802,7 @@ export const lnavFormatSchema = z
|
|
|
810
802
|
value: z.number().optional(),
|
|
811
803
|
})
|
|
812
804
|
.strict()
|
|
813
|
-
.safeParse(value[key])
|
|
805
|
+
.safeParse(value[key])
|
|
814
806
|
if (!result.success) {
|
|
815
807
|
ctx.addIssue({
|
|
816
808
|
path: [key],
|
|
@@ -819,11 +811,11 @@ export const lnavFormatSchema = z
|
|
|
819
811
|
params: {
|
|
820
812
|
issues: result.error.issues,
|
|
821
813
|
},
|
|
822
|
-
})
|
|
814
|
+
})
|
|
823
815
|
}
|
|
824
816
|
}
|
|
825
817
|
if (!evaluated) {
|
|
826
|
-
const result = z.never().safeParse(value[key])
|
|
818
|
+
const result = z.never().safeParse(value[key])
|
|
827
819
|
if (!result.success) {
|
|
828
820
|
ctx.addIssue({
|
|
829
821
|
path: [key],
|
|
@@ -832,7 +824,7 @@ export const lnavFormatSchema = z
|
|
|
832
824
|
params: {
|
|
833
825
|
issues: result.error.issues,
|
|
834
826
|
},
|
|
835
|
-
})
|
|
827
|
+
})
|
|
836
828
|
}
|
|
837
829
|
}
|
|
838
830
|
}
|
|
@@ -879,10 +871,8 @@ export const lnavFormatSchema = z
|
|
|
879
871
|
.optional(),
|
|
880
872
|
})
|
|
881
873
|
.strict()
|
|
882
|
-
.describe(
|
|
883
|
-
|
|
884
|
-
)
|
|
885
|
-
.safeParse(value[key]);
|
|
874
|
+
.describe("The set of values captured by the log message patterns")
|
|
875
|
+
.safeParse(value[key])
|
|
886
876
|
if (!result.success) {
|
|
887
877
|
ctx.addIssue({
|
|
888
878
|
path: [key],
|
|
@@ -891,11 +881,11 @@ export const lnavFormatSchema = z
|
|
|
891
881
|
params: {
|
|
892
882
|
issues: result.error.issues,
|
|
893
883
|
},
|
|
894
|
-
})
|
|
884
|
+
})
|
|
895
885
|
}
|
|
896
886
|
}
|
|
897
887
|
if (!evaluated) {
|
|
898
|
-
const result = z.never().safeParse(value[key])
|
|
888
|
+
const result = z.never().safeParse(value[key])
|
|
899
889
|
if (!result.success) {
|
|
900
890
|
ctx.addIssue({
|
|
901
891
|
path: [key],
|
|
@@ -904,7 +894,7 @@ export const lnavFormatSchema = z
|
|
|
904
894
|
params: {
|
|
905
895
|
issues: result.error.issues,
|
|
906
896
|
},
|
|
907
|
-
})
|
|
897
|
+
})
|
|
908
898
|
}
|
|
909
899
|
}
|
|
910
900
|
}
|
|
@@ -966,9 +956,9 @@ export const lnavFormatSchema = z
|
|
|
966
956
|
)
|
|
967
957
|
.superRefine((value, ctx) => {
|
|
968
958
|
for (const key in value) {
|
|
969
|
-
let evaluated = false
|
|
970
|
-
if (key.match(
|
|
971
|
-
evaluated = true
|
|
959
|
+
let evaluated = false
|
|
960
|
+
if (key.match(new RegExp("^([\\w:;\\._\\-]+)$"))) {
|
|
961
|
+
evaluated = true
|
|
972
962
|
const result = z
|
|
973
963
|
.object({
|
|
974
964
|
paths: z
|
|
@@ -1015,7 +1005,7 @@ export const lnavFormatSchema = z
|
|
|
1015
1005
|
})
|
|
1016
1006
|
.strict()
|
|
1017
1007
|
.describe("The name of the tag to apply")
|
|
1018
|
-
.safeParse(value[key])
|
|
1008
|
+
.safeParse(value[key])
|
|
1019
1009
|
if (!result.success) {
|
|
1020
1010
|
ctx.addIssue({
|
|
1021
1011
|
path: [key],
|
|
@@ -1024,11 +1014,11 @@ export const lnavFormatSchema = z
|
|
|
1024
1014
|
params: {
|
|
1025
1015
|
issues: result.error.issues,
|
|
1026
1016
|
},
|
|
1027
|
-
})
|
|
1017
|
+
})
|
|
1028
1018
|
}
|
|
1029
1019
|
}
|
|
1030
1020
|
if (!evaluated) {
|
|
1031
|
-
const result = z.never().safeParse(value[key])
|
|
1021
|
+
const result = z.never().safeParse(value[key])
|
|
1032
1022
|
if (!result.success) {
|
|
1033
1023
|
ctx.addIssue({
|
|
1034
1024
|
path: [key],
|
|
@@ -1037,7 +1027,7 @@ export const lnavFormatSchema = z
|
|
|
1037
1027
|
params: {
|
|
1038
1028
|
issues: result.error.issues,
|
|
1039
1029
|
},
|
|
1040
|
-
})
|
|
1030
|
+
})
|
|
1041
1031
|
}
|
|
1042
1032
|
}
|
|
1043
1033
|
}
|
|
@@ -1099,9 +1089,9 @@ export const lnavFormatSchema = z
|
|
|
1099
1089
|
)
|
|
1100
1090
|
.superRefine((value, ctx) => {
|
|
1101
1091
|
for (const key in value) {
|
|
1102
|
-
let evaluated = false
|
|
1103
|
-
if (key.match(
|
|
1104
|
-
evaluated = true
|
|
1092
|
+
let evaluated = false
|
|
1093
|
+
if (key.match(new RegExp("^([\\w:;\\._\\-]+)$"))) {
|
|
1094
|
+
evaluated = true
|
|
1105
1095
|
const result = z
|
|
1106
1096
|
.object({
|
|
1107
1097
|
paths: z
|
|
@@ -1148,7 +1138,7 @@ export const lnavFormatSchema = z
|
|
|
1148
1138
|
})
|
|
1149
1139
|
.strict()
|
|
1150
1140
|
.describe("The type of partition to apply")
|
|
1151
|
-
.safeParse(value[key])
|
|
1141
|
+
.safeParse(value[key])
|
|
1152
1142
|
if (!result.success) {
|
|
1153
1143
|
ctx.addIssue({
|
|
1154
1144
|
path: [key],
|
|
@@ -1157,11 +1147,11 @@ export const lnavFormatSchema = z
|
|
|
1157
1147
|
params: {
|
|
1158
1148
|
issues: result.error.issues,
|
|
1159
1149
|
},
|
|
1160
|
-
})
|
|
1150
|
+
})
|
|
1161
1151
|
}
|
|
1162
1152
|
}
|
|
1163
1153
|
if (!evaluated) {
|
|
1164
|
-
const result = z.never().safeParse(value[key])
|
|
1154
|
+
const result = z.never().safeParse(value[key])
|
|
1165
1155
|
if (!result.success) {
|
|
1166
1156
|
ctx.addIssue({
|
|
1167
1157
|
path: [key],
|
|
@@ -1170,7 +1160,7 @@ export const lnavFormatSchema = z
|
|
|
1170
1160
|
params: {
|
|
1171
1161
|
issues: result.error.issues,
|
|
1172
1162
|
},
|
|
1173
|
-
})
|
|
1163
|
+
})
|
|
1174
1164
|
}
|
|
1175
1165
|
}
|
|
1176
1166
|
}
|
|
@@ -1196,9 +1186,9 @@ export const lnavFormatSchema = z
|
|
|
1196
1186
|
)
|
|
1197
1187
|
.superRefine((value, ctx) => {
|
|
1198
1188
|
for (const key in value) {
|
|
1199
|
-
let evaluated = false
|
|
1200
|
-
if (key.match(
|
|
1201
|
-
evaluated = true
|
|
1189
|
+
let evaluated = false
|
|
1190
|
+
if (key.match(new RegExp("^(\\w+)$"))) {
|
|
1191
|
+
evaluated = true
|
|
1202
1192
|
const result = z
|
|
1203
1193
|
.union([
|
|
1204
1194
|
z.string(),
|
|
@@ -1210,7 +1200,7 @@ export const lnavFormatSchema = z
|
|
|
1210
1200
|
})
|
|
1211
1201
|
.strict(),
|
|
1212
1202
|
])
|
|
1213
|
-
.safeParse(value[key])
|
|
1203
|
+
.safeParse(value[key])
|
|
1214
1204
|
if (!result.success) {
|
|
1215
1205
|
ctx.addIssue({
|
|
1216
1206
|
path: [key],
|
|
@@ -1219,11 +1209,11 @@ export const lnavFormatSchema = z
|
|
|
1219
1209
|
params: {
|
|
1220
1210
|
issues: result.error.issues,
|
|
1221
1211
|
},
|
|
1222
|
-
})
|
|
1212
|
+
})
|
|
1223
1213
|
}
|
|
1224
1214
|
}
|
|
1225
1215
|
if (!evaluated) {
|
|
1226
|
-
const result = z.never().safeParse(value[key])
|
|
1216
|
+
const result = z.never().safeParse(value[key])
|
|
1227
1217
|
if (!result.success) {
|
|
1228
1218
|
ctx.addIssue({
|
|
1229
1219
|
path: [key],
|
|
@@ -1232,7 +1222,7 @@ export const lnavFormatSchema = z
|
|
|
1232
1222
|
params: {
|
|
1233
1223
|
issues: result.error.issues,
|
|
1234
1224
|
},
|
|
1235
|
-
})
|
|
1225
|
+
})
|
|
1236
1226
|
}
|
|
1237
1227
|
}
|
|
1238
1228
|
}
|
|
@@ -1285,9 +1275,7 @@ export const lnavFormatSchema = z
|
|
|
1285
1275
|
.object({
|
|
1286
1276
|
field: z
|
|
1287
1277
|
.string()
|
|
1288
|
-
.describe(
|
|
1289
|
-
"The name of the field to substitute at this position",
|
|
1290
|
-
)
|
|
1278
|
+
.describe("The name of the field to substitute at this position")
|
|
1291
1279
|
.optional(),
|
|
1292
1280
|
"default-value": z
|
|
1293
1281
|
.string()
|
|
@@ -1388,9 +1376,9 @@ export const lnavFormatSchema = z
|
|
|
1388
1376
|
)
|
|
1389
1377
|
.superRefine((value, ctx) => {
|
|
1390
1378
|
for (const key in value) {
|
|
1391
|
-
let evaluated = false
|
|
1392
|
-
if (key.match(
|
|
1393
|
-
evaluated = true
|
|
1379
|
+
let evaluated = false
|
|
1380
|
+
if (key.match(new RegExp("^(\\w+)$"))) {
|
|
1381
|
+
evaluated = true
|
|
1394
1382
|
const result = z
|
|
1395
1383
|
.object({
|
|
1396
1384
|
pattern: z
|
|
@@ -1424,7 +1412,7 @@ export const lnavFormatSchema = z
|
|
|
1424
1412
|
})
|
|
1425
1413
|
.strict()
|
|
1426
1414
|
.describe("The set of search tables to be automatically defined")
|
|
1427
|
-
.safeParse(value[key])
|
|
1415
|
+
.safeParse(value[key])
|
|
1428
1416
|
if (!result.success) {
|
|
1429
1417
|
ctx.addIssue({
|
|
1430
1418
|
path: [key],
|
|
@@ -1433,11 +1421,11 @@ export const lnavFormatSchema = z
|
|
|
1433
1421
|
params: {
|
|
1434
1422
|
issues: result.error.issues,
|
|
1435
1423
|
},
|
|
1436
|
-
})
|
|
1424
|
+
})
|
|
1437
1425
|
}
|
|
1438
1426
|
}
|
|
1439
1427
|
if (!evaluated) {
|
|
1440
|
-
const result = z.never().safeParse(value[key])
|
|
1428
|
+
const result = z.never().safeParse(value[key])
|
|
1441
1429
|
if (!result.success) {
|
|
1442
1430
|
ctx.addIssue({
|
|
1443
1431
|
path: [key],
|
|
@@ -1446,7 +1434,7 @@ export const lnavFormatSchema = z
|
|
|
1446
1434
|
params: {
|
|
1447
1435
|
issues: result.error.issues,
|
|
1448
1436
|
},
|
|
1449
|
-
})
|
|
1437
|
+
})
|
|
1450
1438
|
}
|
|
1451
1439
|
}
|
|
1452
1440
|
}
|
|
@@ -1491,9 +1479,9 @@ export const lnavFormatSchema = z
|
|
|
1491
1479
|
)
|
|
1492
1480
|
.superRefine((value, ctx) => {
|
|
1493
1481
|
for (const key in value) {
|
|
1494
|
-
let evaluated = false
|
|
1495
|
-
if (key.match(
|
|
1496
|
-
evaluated = true
|
|
1482
|
+
let evaluated = false
|
|
1483
|
+
if (key.match(new RegExp("^(.+)$"))) {
|
|
1484
|
+
evaluated = true
|
|
1497
1485
|
const result = z
|
|
1498
1486
|
.object({
|
|
1499
1487
|
pattern: z
|
|
@@ -1523,7 +1511,7 @@ export const lnavFormatSchema = z
|
|
|
1523
1511
|
})
|
|
1524
1512
|
.strict()
|
|
1525
1513
|
.describe("The definition of a highlight")
|
|
1526
|
-
.safeParse(value[key])
|
|
1514
|
+
.safeParse(value[key])
|
|
1527
1515
|
if (!result.success) {
|
|
1528
1516
|
ctx.addIssue({
|
|
1529
1517
|
path: [key],
|
|
@@ -1532,11 +1520,11 @@ export const lnavFormatSchema = z
|
|
|
1532
1520
|
params: {
|
|
1533
1521
|
issues: result.error.issues,
|
|
1534
1522
|
},
|
|
1535
|
-
})
|
|
1523
|
+
})
|
|
1536
1524
|
}
|
|
1537
1525
|
}
|
|
1538
1526
|
if (!evaluated) {
|
|
1539
|
-
const result = z.never().safeParse(value[key])
|
|
1527
|
+
const result = z.never().safeParse(value[key])
|
|
1540
1528
|
if (!result.success) {
|
|
1541
1529
|
ctx.addIssue({
|
|
1542
1530
|
path: [key],
|
|
@@ -1545,7 +1533,7 @@ export const lnavFormatSchema = z
|
|
|
1545
1533
|
params: {
|
|
1546
1534
|
issues: result.error.issues,
|
|
1547
1535
|
},
|
|
1548
|
-
})
|
|
1536
|
+
})
|
|
1549
1537
|
}
|
|
1550
1538
|
}
|
|
1551
1539
|
}
|
|
@@ -1566,6 +1554,6 @@ export const lnavFormatSchema = z
|
|
|
1566
1554
|
.optional(),
|
|
1567
1555
|
})
|
|
1568
1556
|
.strict()
|
|
1569
|
-
.describe("The definition of a log file format.")
|
|
1557
|
+
.describe("The definition of a log file format.")
|
|
1570
1558
|
|
|
1571
|
-
export type LnavFormat = z.infer<typeof lnavFormatSchema
|
|
1559
|
+
export type LnavFormat = z.infer<typeof lnavFormatSchema>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flightdeck",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.13",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Jeremy Banka",
|
|
@@ -32,36 +32,36 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@t3-oss/env-core": "0.13.11",
|
|
34
34
|
"arktype": "2.2.0",
|
|
35
|
+
"atom.io": "0.47.4",
|
|
35
36
|
"cron": "4.4.0",
|
|
36
|
-
"
|
|
37
|
-
"comline": "0.4.
|
|
38
|
-
"safedeposit": "0.1.2"
|
|
37
|
+
"safedeposit": "0.1.2",
|
|
38
|
+
"comline": "0.4.8"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@biomejs/js-api": "
|
|
42
|
-
"@biomejs/wasm-nodejs": "2.
|
|
41
|
+
"@biomejs/js-api": "6.0.0",
|
|
42
|
+
"@biomejs/wasm-nodejs": "2.5.0",
|
|
43
43
|
"@types/bun": "npm:bun-types@1.3.14",
|
|
44
|
-
"@types/node": "25.9.
|
|
45
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
44
|
+
"@types/node": "25.9.3",
|
|
45
|
+
"@typescript/native-preview": "7.0.0-dev.20260614.1",
|
|
46
46
|
"concurrently": "10.0.3",
|
|
47
|
-
"eslint": "10.
|
|
47
|
+
"eslint": "10.5.0",
|
|
48
48
|
"json-schema-to-zod": "2.8.1",
|
|
49
49
|
"tsdown": "0.22.2",
|
|
50
50
|
"vitest": "4.1.8",
|
|
51
51
|
"zod": "4.4.3",
|
|
52
|
-
"varmint": "0.5.
|
|
52
|
+
"varmint": "0.5.16"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"gen": "bun ./__scripts__/gen.bun.ts",
|
|
56
56
|
"build": "tsdown && rm -f dist/*.x.d.ts && bun ./__scripts__/build-lnav.bun.ts",
|
|
57
57
|
"schema:flightdeck": "bun ./src/flightdeck.bin.ts --outdir=dist -- schema",
|
|
58
|
-
"lint:biome": "biome check -- .",
|
|
59
58
|
"lint:eslint": "eslint -- .",
|
|
59
|
+
"lint:oxlint": "oxlint --type-aware -c ../../.oxlintrc.jsonc .",
|
|
60
60
|
"lint:types": "tsgo --noEmit",
|
|
61
61
|
"watch:types": "tsgo --watch --noEmit",
|
|
62
62
|
"lint": "concurrently \"bun:lint:*\"",
|
|
63
63
|
"test": "vitest",
|
|
64
64
|
"test:once": "vitest run",
|
|
65
|
-
"postversion": "
|
|
65
|
+
"postversion": "dprint fmt package.json"
|
|
66
66
|
}
|
|
67
67
|
}
|
package/src/flightdeck.lib.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/* oxlint-disable typescript/only-throw-error */
|
|
2
2
|
import type { ChildProcessWithoutNullStreams } from "node:child_process"
|
|
3
3
|
import { execSync, spawn } from "node:child_process"
|
|
4
4
|
import { createServer } from "node:http"
|
|
@@ -628,9 +628,10 @@ export const FLIGHTDECK_LNAV_FORMAT = {
|
|
|
628
628
|
},
|
|
629
629
|
} as const satisfies FlightDeckFormat & LnavFormat
|
|
630
630
|
|
|
631
|
-
export class FlightDeckLogger
|
|
632
|
-
|
|
633
|
-
|
|
631
|
+
export class FlightDeckLogger implements Pick<
|
|
632
|
+
Console,
|
|
633
|
+
`error` | `info` | `warn`
|
|
634
|
+
> {
|
|
634
635
|
public readonly packageName: string
|
|
635
636
|
public readonly serviceName?: string
|
|
636
637
|
public readonly jsonLogging: boolean
|