Skip to content

Commit

Permalink
feat(cli): Enable host option for yarn rw serve (#8385)
Browse files Browse the repository at this point in the history
* Add 'host' option which defaults to toml value - which defaults to 'localhost'

* Update api-server cli-handlers too

* style: save project config calls in var

won't make much of a difference for getPaths but getConfig isn't
memoized so that one is a little excessive to keep calling

* style: save project-config calls where possible

* style: prefer ?? to || for undefined values

* style changes

* enable api-server to take flag

* remove stray nullish accessor

* style: remove needless instantiation

* use existing config in scope

* style

* set host in dev handler

* remove needless null checks

* style: make api command more readable

* add host to watch

* get dev test passing

* get serve test passing

* c

* get watch working

* remove console log

* comments

* style

* fix dev handler when web host is set

* revert to expected webpack behavior

* fix test

---------

Co-authored-by: Dominic Saadi <dominiceliassaadi@gmail.com>
  • Loading branch information
Josh-Walker-GM and jtoar committed May 24, 2023
1 parent 5f03da5 commit 26ad3e2
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 89 deletions.
3 changes: 3 additions & 0 deletions docs/docs/cli-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -1993,6 +1993,7 @@ yarn redwood serve [side]
| ------------------- | ------------------------------------------------------------------------------ |
| `side` | Which side(s) to run. Choices are `api` and `web`. Defaults to `api` and `web` |
| `--port` | What port should the server run on [default: 8911] |
| `--host` | What host should the server run on. This defaults to the value of `web.host` in the `redwood.toml` file which itself defaults to `'localhost'`. |
| `--socket` | The socket the server should run. This takes precedence over port |
### serve api
Expand All @@ -2008,6 +2009,7 @@ This command uses `apiUrl` in your `redwood.toml`. Use this command if you want
| Arguments & Options | Description |
| ------------------- | ----------------------------------------------------------------- |
| `--port` | What port should the server run on [default: 8911] |
| `--host` | What host should the server run on. This defaults to the value of `api.host` in the `redwood.toml` file which itself defaults to `'localhost'`. |
| `--socket` | The socket the server should run. This takes precedence over port |
| `--apiRootPath` | The root path where your api functions are served |
Expand Down Expand Up @@ -2035,6 +2037,7 @@ This command serves the contents in `web/dist`. Use this command if you're debug
| Arguments & Options | Description |
| ------------------- | ------------------------------------------------------------------------------------- |
| `--port` | What port should the server run on [default: 8911] |
| `--host` | What host should the server run on. This defaults to the value of `web.host` in the `redwood.toml` file which itself defaults to `'localhost'`. |
| `--socket` | The socket the server should run. This takes precedence over port |
| `--apiHost` | Forwards requests from the `apiUrl` (defined in `redwood.toml`) to the specified host |
Expand Down
62 changes: 47 additions & 15 deletions packages/api-server/src/cliHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,33 @@ const sendProcessReady = () => {
return process.send && process.send('ready')
}

const redwoodProjectConfig = getConfig()

export const commonOptions = {
port: { default: getConfig().web?.port || 8910, type: 'number', alias: 'p' },
port: {
default: redwoodProjectConfig.web.port,
type: 'number',
alias: 'p',
},
host: {
default: redwoodProjectConfig.web.host,
type: 'string',
alias: 'h',
},
socket: { type: 'string' },
} as const

export const apiCliOptions = {
port: { default: getConfig().api?.port || 8911, type: 'number', alias: 'p' },
port: {
default: redwoodProjectConfig.api.port,
type: 'number',
alias: 'p',
},
host: {
default: redwoodProjectConfig.api.host,
type: 'string',
alias: 'h',
},
socket: { type: 'string' },
apiRootPath: {
alias: ['rootPath', 'root-path'],
Expand All @@ -36,7 +56,16 @@ export const apiCliOptions = {
} as const

export const webCliOptions = {
port: { default: getConfig().web?.port || 8910, type: 'number', alias: 'p' },
port: {
default: redwoodProjectConfig.web.port,
type: 'number',
alias: 'p',
},
host: {
default: redwoodProjectConfig.web.host,
type: 'string',
alias: 'h',
},
socket: { type: 'string' },
apiHost: {
alias: 'api-host',
Expand All @@ -46,7 +75,7 @@ export const webCliOptions = {
} as const

export const apiServerHandler = async (options: ApiServerArgs) => {
const { port, socket, apiRootPath } = options
const { port, host, socket, apiRootPath } = options
const tsApiServer = Date.now()
process.stdout.write(c.dim(c.italic('Starting API Server...\n')))

Expand All @@ -57,14 +86,15 @@ export const apiServerHandler = async (options: ApiServerArgs) => {

const http = startFastifyServer({
port,
host,
socket,
fastify,
}).ready(() => {
console.log(c.italic(c.dim('Took ' + (Date.now() - tsApiServer) + ' ms')))

const on = socket
? socket
: c.magenta(`http://localhost:${port}${apiRootPath}`)
: c.magenta(`http://${host}:${port}${apiRootPath}`)
console.log(`API listening on ${on}`)
const graphqlEnd = c.magenta(`${apiRootPath}graphql`)
console.log(`GraphQL endpoint at ${graphqlEnd}`)
Expand All @@ -76,10 +106,10 @@ export const apiServerHandler = async (options: ApiServerArgs) => {
}

export const bothServerHandler = async (options: BothServerArgs) => {
const { port, socket } = options
const { port, host, socket } = options
const tsServer = Date.now()
process.stdout.write(c.dim(c.italic('Starting API and Web Servers...\n')))
const apiRootPath = coerceRootPath(getConfig().web.apiUrl)
const apiRootPath = coerceRootPath(redwoodProjectConfig.web.apiUrl)

let fastify = createFastifyInstance()

Expand All @@ -89,15 +119,16 @@ export const bothServerHandler = async (options: BothServerArgs) => {

startFastifyServer({
port,
host,
socket,
fastify,
}).ready(() => {
console.log(c.italic(c.dim('Took ' + (Date.now() - tsServer) + ' ms')))
const on = socket
? socket
: c.magenta(`http://localhost:${port}${apiRootPath}`)
const webServer = c.green(`http://localhost:${port}`)
const apiServer = c.magenta(`http://localhost:${port}`)
: c.magenta(`http://${host}:${port}${apiRootPath}`)
const webServer = c.green(`http://${host}:${port}`)
const apiServer = c.magenta(`http://${host}:${port}`)
console.log(`Web server started on ${webServer}`)
console.log(`API serving from ${apiServer}`)
console.log(`API listening on ${on}`)
Expand All @@ -108,14 +139,14 @@ export const bothServerHandler = async (options: BothServerArgs) => {
}

export const webServerHandler = async (options: WebServerArgs) => {
const { port, socket, apiHost } = options
const { port, host, socket, apiHost } = options
const tsServer = Date.now()
process.stdout.write(c.dim(c.italic('Starting Web Server...\n')))
const apiUrl = getConfig().web.apiUrl
const apiUrl = redwoodProjectConfig.web.apiUrl
// Construct the graphql url from apiUrl by default
// But if apiGraphQLUrl is specified, use that instead
const graphqlEndpoint = coerceRootPath(
getConfig().web.apiGraphQLUrl ?? `${apiUrl}/graphql`
redwoodProjectConfig.web.apiGraphQLUrl ?? `${apiUrl}/graphql`
)

let fastify = createFastifyInstance()
Expand All @@ -131,15 +162,16 @@ export const webServerHandler = async (options: WebServerArgs) => {
}

startFastifyServer({
port: port,
port,
host,
socket,
fastify,
}).ready(() => {
console.log(c.italic(c.dim('Took ' + (Date.now() - tsServer) + ' ms')))
if (socket) {
console.log(`Listening on ` + c.magenta(`${socket}`))
}
const webServer = c.green(`http://localhost:${port}`)
const webServer = c.green(`http://${host}:${port}`)
console.log(`Web server started on ${webServer}`)
console.log(`GraphQL endpoint is set to ` + c.magenta(`${graphqlEndpoint}`))
sendProcessReady()
Expand Down
3 changes: 2 additions & 1 deletion packages/api-server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import { FastifyInstance } from 'fastify'

export interface HttpServerParams {
port: number
host?: string
socket?: string
fastify: FastifyInstance
}

export const startServer = ({
port = 8911,
host = 'localhost',
socket,
fastify,
}: HttpServerParams) => {
const host = 'localhost'
const serverPort = socket ? parseInt(socket) : port

fastify.listen({ port: serverPort, host })
Expand Down
40 changes: 24 additions & 16 deletions packages/api-server/src/watch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env node
// This script is called by the `yarn rw dev` command. Specifically, it's the api command.

import { fork } from 'child_process'
import type { ChildProcess } from 'child_process'
Expand All @@ -16,6 +17,9 @@ import { buildApi } from '@redwoodjs/internal/dist/build/api'
import { loadAndValidateSdls } from '@redwoodjs/internal/dist/validateSchema'
import { getPaths, ensurePosixPath, getConfig } from '@redwoodjs/project-config'

const redwoodProjectPaths = getPaths()
const redwoodProjectConfig = getConfig()

const argv = yargs(hideBin(process.argv))
.option('debug-port', {
alias: 'dp',
Expand All @@ -26,15 +30,19 @@ const argv = yargs(hideBin(process.argv))
alias: 'p',
description: 'Port',
type: 'number',
default: redwoodProjectConfig.api.port,
})
.option('host', {
alias: 'h',
description: 'Host',
type: 'string',
default: redwoodProjectConfig.api.host,
})
.help()
.alias('help', 'h')
.parseSync()

const rwjsPaths = getPaths()

// If this is run via the yarn rw dev command, this will have already been called.
dotenv.config({
path: rwjsPaths.base,
path: redwoodProjectPaths.base,
})

// TODO:
Expand Down Expand Up @@ -77,9 +85,9 @@ const rebuildApiServer = () => {
}

// OpenTelemetry SDK Setup
if (getConfig().experimental.opentelemetry.enabled) {
if (redwoodProjectConfig.experimental.opentelemetry.enabled) {
const opentelemetrySDKScriptPath =
getConfig().experimental.opentelemetry.apiSdk
redwoodProjectConfig.experimental.opentelemetry.apiSdk
if (opentelemetrySDKScriptPath) {
console.log(
`Setting up OpenTelemetry using the setup file: ${opentelemetrySDKScriptPath}`
Expand All @@ -101,12 +109,10 @@ const rebuildApiServer = () => {
forkOpts.execArgv = forkOpts.execArgv.concat([`--inspect=${debugPort}`])
}

const port = argv.port ?? getConfig().api.port

// Start API server
httpServerProcess = fork(
path.join(__dirname, 'index.js'),
['api', '--port', port.toString()],
['api', '--port', argv.port.toString(), '--host', `${argv.host}`],
forkOpts
)
} catch (e) {
Expand All @@ -126,16 +132,16 @@ const delayRestartServer = debounce(
)

// NOTE: the file comes through as a unix path, even on windows
// So we need to convert the rwjsPaths
// So we need to convert the redwoodProjectPaths

const IGNORED_API_PATHS = [
'api/dist', // use this, because using rwjsPaths.api.dist seems to not ignore on first build
rwjsPaths.api.types,
rwjsPaths.api.db,
'api/dist', // use this, because using redwoodProjectPaths.api.dist seems to not ignore on first build
redwoodProjectPaths.api.types,
redwoodProjectPaths.api.db,
].map((path) => ensurePosixPath(path))

chokidar
.watch(rwjsPaths.api.base, {
.watch(redwoodProjectPaths.api.base, {
persistent: true,
ignoreInitial: true,
ignored: (file: string) => {
Expand Down Expand Up @@ -174,7 +180,9 @@ chokidar
}

console.log(
c.dim(`[${eventName}] ${filePath.replace(rwjsPaths.api.base, '')}`)
c.dim(
`[${eventName}] ${filePath.replace(redwoodProjectPaths.api.base, '')}`
)
)
delayRestartServer.cancel()
delayRestartServer()
Expand Down
8 changes: 6 additions & 2 deletions packages/cli/src/commands/__tests__/dev.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe('yarn rw dev', () => {
getConfig.mockReturnValue({
web: {
port: 8910,
host: 'localhost',
},
api: {
port: 8911,
Expand All @@ -100,7 +101,7 @@ describe('yarn rw dev', () => {
)

expect(apiCommand.command).toMatchInlineSnapshot(
`"yarn cross-env NODE_ENV=development NODE_OPTIONS=--enable-source-maps yarn nodemon --quiet --watch "/mocked/project/redwood.toml" --exec "yarn rw-api-server-watch --port 8911 --debug-port 18911 | rw-log-formatter""`
`"yarn cross-env NODE_ENV=development NODE_OPTIONS=--enable-source-maps yarn nodemon --quiet --watch "/mocked/project/redwood.toml" --exec "yarn rw-api-server-watch --port 8911 --host '::' --debug-port 18911 | rw-log-formatter""`
)

expect(generateCommand.command).toEqual('yarn rw-gen-watch')
Expand All @@ -110,6 +111,7 @@ describe('yarn rw dev', () => {
getConfig.mockReturnValue({
web: {
port: 8910,
host: 'localhost',
},
api: {
port: 8911,
Expand All @@ -127,14 +129,15 @@ describe('yarn rw dev', () => {
const apiCommand = find(concurrentlyArgs, { name: 'api' })

expect(apiCommand.command).toContain(
'yarn rw-api-server-watch --port 8911 --debug-port 90909090'
"yarn rw-api-server-watch --port 8911 --host '::' --debug-port 90909090"
)
})

it('Can disable debugger by setting toml to false', async () => {
getConfig.mockReturnValue({
web: {
port: 8910,
host: 'localhost',
},
api: {
port: 8911,
Expand All @@ -157,6 +160,7 @@ describe('yarn rw dev', () => {
getConfig.mockReturnValue({
web: {
port: 8910,
host: 'localhost',
bundler: 'vite', // <-- enable vite mode
},
api: {
Expand Down
11 changes: 10 additions & 1 deletion packages/cli/src/commands/__tests__/serve.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ jest.mock('@redwoodjs/project-config', () => {
},
getConfig: () => {
return {
api: {},
web: {
host: 'localhost',
},
api: {
host: 'localhost',
},
}
},
}
Expand Down Expand Up @@ -67,6 +72,7 @@ describe('yarn rw serve', () => {
expect(apiServerHandler).toHaveBeenCalledWith(
expect.objectContaining({
port: 5555,
host: 'localhost',
apiRootPath: expect.stringMatching(/^\/?funkyFunctions\/?$/),
})
)
Expand All @@ -82,6 +88,7 @@ describe('yarn rw serve', () => {
expect(apiServerHandler).toHaveBeenCalledWith(
expect.objectContaining({
port: 5555,
host: 'localhost',
rootPath: expect.stringMatching(/^\/?funkyFunctions\/nested\/$/),
})
)
Expand All @@ -97,6 +104,7 @@ describe('yarn rw serve', () => {
expect(webServerHandler).toHaveBeenCalledWith(
expect.objectContaining({
port: 9898,
host: 'localhost',
socket: 'abc',
apiHost: 'https://myapi.redwood/api',
})
Expand All @@ -111,6 +119,7 @@ describe('yarn rw serve', () => {
expect(bothServerHandler).toHaveBeenCalledWith(
expect.objectContaining({
port: 9898,
host: 'localhost',
socket: 'abc',
})
)
Expand Down
Loading

0 comments on commit 26ad3e2

Please sign in to comment.