Skip to content

Commit

Permalink
feat(dev): add startup checks; fixes #25
Browse files Browse the repository at this point in the history
  • Loading branch information
justmoon committed Dec 1, 2023
1 parent 6bf2512 commit 060a4c1
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 0 deletions.
155 changes: 155 additions & 0 deletions packages/app-dev/src/backend/functions/verify-prerequisites.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import chalk from "chalk"
import { $ } from "execa"

import { lookup } from "node:dns/promises"
import { readFile } from "node:fs/promises"

import { isErrorWithCode } from "@dassie/lib-type-utils"

const NODE_VERSION_PATH = new URL(
"../../../../../.node-version",
import.meta.url,
).pathname

export const verifyPrerequisites = async () => {
// Windows is not supported
{
if (process.platform === "win32") {
console.error(
`prerequisite check failed: unsupported platform
Dassie does not currently support Windows.
${chalk.bold(
"Consider using Windows Subsystem for Linux (WSL), a container, or a virtual machine.",
)}
`,
)
return false
}
}

// Verify Node.js version is correct
{
const requiredNodeVersion = await readFile(NODE_VERSION_PATH, "utf8")

const actualNodeVersion = process.version

if (actualNodeVersion.trim() !== requiredNodeVersion.trim()) {
console.error(
`prerequisite check failed: incorrect node version
Required Node.js version: ${chalk.bold.green(requiredNodeVersion)}
Your Node.js version: ${chalk.bold.red(actualNodeVersion)}
${chalk.bold(
"We recommend you use a node version manager which supports .node-version",
)}
Here is a list of possible options: https://stackoverflow.com/q/27425852
If you don't want to choose, try fnm: https://github.com/Schniz/fnm
`,
)
return false
}
}

// Verify that OpenSSL is installed
{
try {
await $`openssl version`
} catch (error: unknown) {
if (isErrorWithCode(error, "ENOENT")) {
console.error(
`prerequisite check failed: openssl is not in path
${chalk.bold(
"Please install OpenSSL from https://github.com/FiloSottile/mkcert",
)}
`,
)
return false
}

console.error("prerequisite check failed: error while checking mkcert", {
error,
})
return false
}
}

// Verify that mkcert is installed
{
try {
await $`mkcert --version`
} catch (error: unknown) {
if (isErrorWithCode(error, "ENOENT")) {
console.error(
`prerequisite check failed: mkcert is not in path
${chalk.bold(
"Please install mkcert from https://github.com/FiloSottile/mkcert",
)}
`,
)
return false
}

throw error
}
}

// Check that NODE_EXTRA_CA_CERTS is set to the mkcert root certificate
{
const { stdout } = await $`mkcert -CAROOT`

const expectedPath = `${stdout.trim()}/rootCA.pem`

if (process.env["NODE_EXTRA_CA_CERTS"] !== expectedPath) {
console.warn(
`prerequisite check failed: NODE_EXTRA_CA_CERTS is not set to mkcert root certificate
$(mkcert -CAROOT)/rootCA.pem: ${chalk.bold.green(expectedPath)}
NODE_EXTRA_CA_CERTS: ${chalk.bold.red(process.env["NODE_EXTRA_CA_CERTS"])}
${chalk.bold('Please set NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"')}

This comment has been minimized.

Copy link
@sublimator

sublimator Dec 2, 2023

Contributor

Hrmm, why can't this just be defaulted??

`,
)
return false
}
}

// Check that *.localhost resolves to 127.0.0.1
{
try {
const { address } = await lookup("d999.localhost", { family: 4 })

if (address !== "127.0.0.1") {
console.error(
`prerequisite check failed: *.localhost does not resolve to 127.0.0.1
*.localhost should resolve to: ${chalk.bold.green("127.0.0.1")}
*.localhost actually resolves to: ${chalk.bold.red(address)}
`,
)
return false
}
} catch (error: unknown) {
if (isErrorWithCode(error, "ENOTFOUND")) {
console.error(
`prerequisite check failed: *.localhost does not resolve to anything
*.localhost should resolve to: ${chalk.bold.green("127.0.0.1")}
*.localhost does not resolve to anything
`,
)
return false
}

throw error
}
}

return true
}
9 changes: 9 additions & 0 deletions packages/app-dev/src/backend/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { RegisterReactiveLoggerActor } from "./actors/register-reactive-logger"
import { RunNodesActor } from "./actors/run-nodes"
import { DebugUiServerActor } from "./actors/serve-debug-ui"
import { ListenForRpcWebSocketActor } from "./actors/serve-rpc"
import { verifyPrerequisites } from "./functions/verify-prerequisites"
import { ViteNodeServer } from "./unconstructables/vite-node-server"
import { ViteServer } from "./unconstructables/vite-server"

Expand All @@ -24,6 +25,14 @@ export const RootActor = () =>
sig.run(RegisterReactiveLoggerActor)
sig.run(ApplyDebugLoggingScopes)

const isValidEnvironment = await verifyPrerequisites()

if (!isValidEnvironment) {
process.exitCode = 1
void sig.reactor.dispose()
return
}

await sig.run(ListenForRpcWebSocketActor)
await sig.run(DebugUiServerActor)

Expand Down

0 comments on commit 060a4c1

Please sign in to comment.