Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/BaseCommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ class BaseCommand extends Command {
async catch (error) {
const { flags } = await this.parse(this.prototype)
if (flags.verbose) {
aioLogger.error(error)
if (error.diagnostics) {
aioLogger.error(JSON.stringify(error.diagnostics, null, 2))
} else {
aioLogger.error(error)
}
}
this.handleError(error, flags.verbose)
}
Expand Down
18 changes: 12 additions & 6 deletions src/commands/app/dev/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,14 @@ class Dev extends BaseCommand {
* @param {object} config the config for the app
*/
async verifyActionConfig (config) {
const actionConfig = config.manifest.full.packages
const actionConfig = config.manifest?.full?.packages
const errors = []

// there might not be a runtime manifest, that's ok
if (!actionConfig) {
return
}

// 1. all actions in sequences must exist
Object.entries(actionConfig).forEach(([_, pkg]) => { // iterate through each package
const sequences = pkg?.sequences || {}
Expand Down Expand Up @@ -140,7 +145,9 @@ class Dev extends BaseCommand {

async runAppBuild (extensionConfig) {
this.log('Building the app...')
await buildActions(extensionConfig, null /* filterActions[] */, false /* skipCheck */)
if (extensionConfig.app.hasBackend) {
await buildActions(extensionConfig, null /* filterActions[] */, false /* skipCheck */)
}
}

async runOneExtensionPoint (name, config, flags) {
Expand Down Expand Up @@ -204,12 +211,11 @@ class Dev extends BaseCommand {
}
if (hasBackend) {
this.displayActionUrls(actionUrls)
const { watcherCleanup } = await createWatcher({ config, isLocal: true, inprocHook })
cleanup.add(() => watcherCleanup(), 'cleaning up action watcher...')
cleanup.wait()
}
this.log('press CTRL+C to terminate the dev environment')

const { watcherCleanup } = await createWatcher({ config, isLocal: true, inprocHook })
cleanup.add(() => watcherCleanup(), 'cleaning up action watcher...')
cleanup.wait()
}

async getOrGenerateCertificates ({ pubCertPath, privateKeyPath, devKeysDir, devKeysConfigKey, maxWaitTimeSeconds = 20 }) {
Expand Down
74 changes: 35 additions & 39 deletions src/lib/run-dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ async function runDev (runOptions, config, _inprocHookRunner) {
const distFolder = devConfig.actions.dist

const serveLogger = coreLogger('serve', { level: process.env.LOG_LEVEL, provider: 'winston' })
serveLogger.debug('config.manifest is', JSON.stringify(devConfig.manifest.full.packages, null, 2))
serveLogger.debug('config.manifest is', JSON.stringify(devConfig.manifest?.full?.packages, null, 2))

const actionConfig = devConfig.manifest.full.packages
const actionConfig = devConfig.manifest?.full?.packages
const hasFrontend = devConfig.app.hasFrontend
const hasBackend = devConfig.app.hasBackend
const httpsSettings = runOptions?.parcel?.https
Expand Down Expand Up @@ -117,55 +117,51 @@ async function runDev (runOptions, config, _inprocHookRunner) {
if (hasFrontend) {
const liveReloadServer = livereload.createServer({ https: serverOptions })
liveReloadServer.watch(devConfig.web.distDev)
serveLogger.info(`Watching web folder ${devConfig.web.distDev}...`)
liveReloadServer.server.once('connection', () => {
setTimeout(() => {
liveReloadServer.refresh('/')
}, 100)
})

try {
utils.writeConfig(devConfig.web.injectedConfig, actionUrls)
utils.writeConfig(devConfig.web.injectedConfig, actionUrls)

const bundlerPortToUse = parseInt(process.env.BUNDLER_PORT) || BUNDLER_DEFAULT_PORT
const bundlerPort = await getPort({ port: bundlerPortToUse })
const bundlerPortToUse = parseInt(process.env.BUNDLER_PORT) || BUNDLER_DEFAULT_PORT
const bundlerPort = await getPort({ port: bundlerPortToUse })

if (bundlerPort !== bundlerPortToUse) {
serveLogger.info(`Could not use bundler port ${bundlerPortToUse}, using port ${bundlerPort} instead`)
}
if (bundlerPort !== bundlerPortToUse) {
serveLogger.info(`Could not use bundler port ${bundlerPortToUse}, using port ${bundlerPort} instead`)
}

const entries = devConfig.web.src + '/**/*.html'
bundleOptions.serveOptions = {
port: bundlerPort,
https: httpsSettings
}
const entries = devConfig.web.src + '/**/*.html'
bundleOptions.serveOptions = {
port: bundlerPort,
https: httpsSettings
}

const bundler = await bundle(entries, devConfig.web.distDev, bundleOptions, serveLogger.debug.bind(serveLogger))
await bundler.run() // run it once
const bundler = await bundle(entries, devConfig.web.distDev, bundleOptions, serveLogger.debug.bind(serveLogger))
await bundler.run() // run it once

subscription = await bundler.watch((err, event) => {
if (err) {
// fatal error
throw err
}
subscription = await bundler.watch((err, event) => {
if (err) {
// fatal error
throw err
}

serveLogger.info(`${event.changedAssets.size} static asset(s) changed`)
const limit = runOptions.verbose ? Infinity : CHANGED_ASSETS_PRINT_LIMIT
if (event.changedAssets.size <= limit) {
event.changedAssets.forEach((value, key, map) => {
serveLogger.info('\t-->', value)
})
}
if (event.type === 'buildSuccess') {
const bundles = event.bundleGraph.getBundles()
serveLogger.info(`✨ Built ${bundles.length} bundles in ${event.buildTime}ms!`)
} else if (event.type === 'buildFailure') {
serveLogger.error(event.diagnostics)
}
})
} catch (err) {
console.error(err)
serveLogger.error(err.diagnostics)
}
serveLogger.info(`${event.changedAssets.size} static asset(s) changed`)
const limit = runOptions.verbose ? Infinity : CHANGED_ASSETS_PRINT_LIMIT
if (event.changedAssets.size <= limit) {
event.changedAssets.forEach((value, key, map) => {
serveLogger.info('\t-->', value)
})
}
if (event.type === 'buildSuccess') {
const bundles = event.bundleGraph.getBundles()
serveLogger.info(`✨ Built ${bundles.length} bundles in ${event.buildTime}ms!`)
} else if (event.type === 'buildFailure') {
serveLogger.error(event.diagnostics)
}
})
}

const app = express()
Expand Down
9 changes: 9 additions & 0 deletions test/BaseCommand.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ describe('catch', () => {
expect(command.error).toHaveBeenCalledWith(expect.stringContaining(errorList.join('\n')))
})

test('will handle errors with diagnostics property when using --verbose flag', async () => {
command.argv = ['--verbose']
const errorWithDiagnostics = new Error('fake error')
errorWithDiagnostics.diagnostics = { some: 'property ' }
await command.catch(errorWithDiagnostics)

expect(command.error).toHaveBeenCalledWith(expect.stringContaining('fake error'))
})

test('will handle errors without stack traces when using --verbose flag', async () => {
command.argv = ['--verbose']
const errorWithoutStack = new Error('fake error')
Expand Down
2 changes: 0 additions & 2 deletions test/commands/app/dev/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ describe('run', () => {
}

command.getAppExtConfigs.mockResolvedValueOnce({ myextension: appConfig })
const serverCleanup = () => console.log('server cleanup')
mockRunDev.mockResolvedValue({
frontEndUrl: 'https://localhost:9080',
actionUrls: {
Expand Down Expand Up @@ -235,7 +234,6 @@ describe('run', () => {
test('run, no flags, has frontend, no backend', async () => {
command.argv = []
const appConfig = {
manifest: { full: { packages: {} } },
hooks: {
},
app: {
Expand Down
74 changes: 47 additions & 27 deletions test/lib/run-dev.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1449,23 +1449,22 @@ describe('runDev', () => {
}
})

test('has front end, has back end, bundler watch error', async () => {
const actionPath = fixturePath('actions/successNoReturnAction.js')
const config = createConfig({
hasFrontend: true,
hasBackend: true,
packageName: 'mypackage',
actions: {
myaction: {
function: actionPath
describe('has front end, has back end, bundler errors', () => {
test('bundler watch error', async () => {
const actionPath = fixturePath('actions/successNoReturnAction.js')
const config = createConfig({
hasFrontend: true,
hasBackend: true,
packageName: 'mypackage',
actions: {
myaction: {
function: actionPath
}
}
}
})
const runOptions = createRunOptions({ cert: 'my-cert', key: 'my-key' })
const hookRunner = () => {}
})
const runOptions = createRunOptions({ cert: 'my-cert', key: 'my-key' })
const hookRunner = () => {}

// 1. error in bundle.watch
{
const bundleEvent = createBundlerEvent()
const bundleErr = { diagnostics: 'something went wrong' }
mockLibWeb.bundle.mockResolvedValue({
Expand All @@ -1475,16 +1474,24 @@ describe('runDev', () => {
}
})

const { frontendUrl, actionUrls, serverCleanup } = await runDev(runOptions, config, hookRunner)
await serverCleanup()
await expect(runDev(runOptions, config, hookRunner)).rejects.toEqual(bundleErr)
})

expect(frontendUrl).toBeDefined()
expect(Object.keys(actionUrls).length).toBeGreaterThan(0)
expect(mockLogger.error).toHaveBeenCalledWith(bundleErr.diagnostics)
}
test('bundler build error', async () => {
const actionPath = fixturePath('actions/successNoReturnAction.js')
const config = createConfig({
hasFrontend: true,
hasBackend: true,
packageName: 'mypackage',
actions: {
myaction: {
function: actionPath
}
}
})
const runOptions = createRunOptions({ cert: 'my-cert', key: 'my-key' })
const hookRunner = () => {}

// 2. error in bundle build
{
const bundlerEventParams = { type: 'buildFailure', diagnostics: 'something went wrong' }
const bundleEvent = createBundlerEvent(bundlerEventParams)
mockLibWeb.bundle.mockResolvedValue({
Expand All @@ -1500,10 +1507,23 @@ describe('runDev', () => {
expect(frontendUrl).toBeDefined()
expect(Object.keys(actionUrls).length).toBeGreaterThan(0)
expect(mockLogger.error).toHaveBeenCalledWith(bundlerEventParams.diagnostics)
}
})

test('unknown build event type', async () => {
const actionPath = fixturePath('actions/successNoReturnAction.js')
const config = createConfig({
hasFrontend: true,
hasBackend: true,
packageName: 'mypackage',
actions: {
myaction: {
function: actionPath
}
}
})
const runOptions = createRunOptions({ cert: 'my-cert', key: 'my-key' })
const hookRunner = () => {}

// 2. unknown buildEvent type
{
const bundlerEventParams = { type: 'unknown_event_type', diagnostics: 'something went wrong 2' }
const bundleEvent = createBundlerEvent(bundlerEventParams)
mockLibWeb.bundle.mockResolvedValue({
Expand All @@ -1518,7 +1538,7 @@ describe('runDev', () => {

expect(frontendUrl).toBeDefined()
expect(Object.keys(actionUrls).length).toBeGreaterThan(0)
}
})
})
})

Expand Down
Loading