Skip to content

Commit

Permalink
Improve how the api-server watch command works (redwoodjs#9841)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobbe authored Jan 19, 2024
1 parent 3188f18 commit b759ad1
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 32 deletions.
7 changes: 3 additions & 4 deletions packages/api-server/src/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const argv = yargs(hideBin(process.argv))
description: 'Debugging port',
type: 'number',
})
// `port` is not used when server-file is used
.option('port', {
alias: 'p',
description: 'Port',
Expand Down Expand Up @@ -133,15 +134,13 @@ const buildAndRestart = async ({
// Check if experimental server file exists
const serverFile = resolveFile(`${rwjsPaths.api.dist}/server`)
if (serverFile) {
const separator = chalk.hex('#ff845e')(
'------------------------------------------------------------------'
)
const separator = chalk.hex('#ff845e')('-'.repeat(79))
console.log(
[
separator,
`🧪 ${chalk.green('Experimental Feature')} 🧪`,
separator,
'Using the experimental API server file at api/dist/server.js',
'Using the experimental API server file at api/dist/server.js (in watch mode)',
separator,
].join('\n')
)
Expand Down
13 changes: 8 additions & 5 deletions packages/cli/src/commands/__tests__/dev.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ jest.mock('@redwoodjs/internal/dist/dev', () => {
})

jest.mock('@redwoodjs/project-config', () => {
const actualProjectConfig = jest.requireActual('@redwoodjs/project-config')

return {
getConfig: jest.fn(),
getConfigPath: () => '/mocked/project/redwood.toml',
resolveFile: actualProjectConfig.resolveFile,
getPaths: () => {
return {
api: {
Expand Down Expand Up @@ -104,8 +107,8 @@ describe('yarn rw dev', () => {
'yarn cross-env NODE_ENV=development rw-vite-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""`
expect(apiCommand.command.replace(/\s+/g, ' ')).toEqual(
'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"'
)

expect(generateCommand.command).toEqual('yarn rw-gen-watch')
Expand Down Expand Up @@ -143,8 +146,8 @@ describe('yarn rw dev', () => {
'yarn cross-env NODE_ENV=development rw-dev-fe'
)

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""`
expect(apiCommand.command.replace(/\s+/g, ' ')).toEqual(
'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"'
)

expect(generateCommand.command).toEqual('yarn rw-gen-watch')
Expand Down Expand Up @@ -175,7 +178,7 @@ describe('yarn rw dev', () => {

const apiCommand = find(concurrentlyArgs, { name: 'api' })

expect(apiCommand.command).toContain(
expect(apiCommand.command.replace(/\s+/g, ' ')).toContain(
'yarn rw-api-server-watch --port 8911 --debug-port 90909090'
)
})
Expand Down
74 changes: 51 additions & 23 deletions packages/cli/src/commands/devHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import fs from 'fs-extra'

import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers'
import { shutdownPort } from '@redwoodjs/internal/dist/dev'
import { getConfig, getConfigPath } from '@redwoodjs/project-config'
import {
getConfig,
getConfigPath,
resolveFile,
} from '@redwoodjs/project-config'
import { errorTelemetry } from '@redwoodjs/telemetry'

import { getPaths } from '../lib'
Expand All @@ -32,6 +36,9 @@ export const handler = async ({

const rwjsPaths = getPaths()

// Check if experimental server file exists
const serverFile = resolveFile(`${rwjsPaths.api.dist}/server`)

// Starting values of ports from config (redwood.toml)
let apiPreferredPort = parseInt(getConfig().api.port)
let webPreferredPort = parseInt(getConfig().web.port)
Expand All @@ -42,8 +49,10 @@ export const handler = async ({
let webAvailablePort = webPreferredPort
let webPortChangeNeeded = false

// Check api port
if (side.includes('api')) {
// Check api port, unless there's a serverFile. If there is a serverFile, we
// don't know what port will end up being used in the end. It's up to the
// author of the server file to decide and handle that
if (side.includes('api') && !serverFile) {
apiAvailablePort = await getFreePort(apiPreferredPort)
if (apiAvailablePort === -1) {
exitWithError(undefined, {
Expand Down Expand Up @@ -76,17 +85,23 @@ export const handler = async ({

// Check for port conflict and exit with message if found
if (apiPortChangeNeeded || webPortChangeNeeded) {
let message = `The currently configured ports for the development server are unavailable. Suggested changes to your ports, which can be changed in redwood.toml, are:\n`
message += apiPortChangeNeeded
? ` - API to use port ${apiAvailablePort} instead of your currently configured ${apiPreferredPort}\n`
: ``
message += webPortChangeNeeded
? ` - Web to use port ${webAvailablePort} instead of your currently configured ${webPreferredPort}\n`
: ``
message += `\nCannot run the development server until your configured ports are changed or become available.`
exitWithError(undefined, {
message,
})
const message = [
'The currently configured ports for the development server are',
'unavailable. Suggested changes to your ports, which can be changed in',
'redwood.toml, are:\n',
apiPortChangeNeeded && ` - API to use port ${apiAvailablePort} instead`,
apiPortChangeNeeded && 'of your currently configured',
apiPortChangeNeeded && `${apiPreferredPort}\n`,
webPortChangeNeeded && ` - Web to use port ${webAvailablePort} instead`,
webPortChangeNeeded && 'of your currently configured',
webPortChangeNeeded && `${webPreferredPort}\n`,
'\nCannot run the development server until your configured ports are',
'changed or become available.',
]
.filter(Boolean)
.join(' ')

exitWithError(undefined, { message })
}

if (side.includes('api')) {
Expand All @@ -104,13 +119,17 @@ export const handler = async ({
console.error(c.error(e.message))
}

try {
await shutdownPort(apiAvailablePort)
} catch (e) {
errorTelemetry(process.argv, `Error shutting down "api": ${e.message}`)
console.error(
`Error whilst shutting down "api" port: ${c.error(e.message)}`
)
// Again, if a server file is configured, we don't know what port it'll end
// up using
if (!serverFile) {
try {
await shutdownPort(apiAvailablePort)
} catch (e) {
errorTelemetry(process.argv, `Error shutting down "api": ${e.message}`)
console.error(
`Error whilst shutting down "api" port: ${c.error(e.message)}`
)
}
}
}

Expand Down Expand Up @@ -142,7 +161,7 @@ export const handler = async ({
return `--debug-port ${apiDebugPortInToml}`
}

// Dont pass in debug port flag, unless configured
// Don't pass in debug port flag, unless configured
return ''
}

Expand Down Expand Up @@ -178,7 +197,16 @@ export const handler = async ({
const jobs = {
api: {
name: 'api',
command: `yarn cross-env NODE_ENV=development NODE_OPTIONS="${getDevNodeOptions()}" yarn nodemon --quiet --watch "${redwoodConfigPath}" --exec "yarn rw-api-server-watch --port ${apiAvailablePort} ${getApiDebugFlag()} | rw-log-formatter"`,
command: [
`yarn cross-env NODE_ENV=development NODE_OPTIONS="${getDevNodeOptions()}"`,
' yarn nodemon',
' --quiet',
` --watch "${redwoodConfigPath}"`,
' --exec "yarn rw-api-server-watch',
` --port ${apiAvailablePort}`,
` ${getApiDebugFlag()}`,
' | rw-log-formatter"',
].join(' '),
prefixColor: 'cyan',
runWhen: () => fs.existsSync(rwjsPaths.api.src),
},
Expand Down

0 comments on commit b759ad1

Please sign in to comment.