Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: netlify/cli
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.37.38
Choose a base ref
...
head repository: netlify/cli
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.38.0
Choose a head ref
  • 3 commits
  • 13 files changed
  • 4 contributors

Commits on Jun 22, 2021

  1. 1

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ac2d25e View commit details
  2. fix(deps): update dependency @netlify/plugin-edge-handlers to ^1.11.19 (

    #2726)
    
    Co-authored-by: Renovate Bot <bot@renovateapp.com>
    renovate[bot] and renovate-bot authored Jun 22, 2021
    1

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    eff70a9 View commit details
  3. chore: release 3.38.0 (#2724)

    Co-authored-by: token-generator-app[bot] <82042599+token-generator-app[bot]@users.noreply.github.com>
    token-generator-app[bot] authored Jun 22, 2021
    1

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3fedeb3 View commit details
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

## [3.38.0](https://www.github.com/netlify/cli/compare/v3.37.38...v3.38.0) (2021-06-22)


### Features

* reorganise functions serving logic ([#2714](https://www.github.com/netlify/cli/issues/2714)) ([ac2d25e](https://www.github.com/netlify/cli/commit/ac2d25ea5f007031a6f9896625e9bfd0f9b3c5b7))


### Bug Fixes

* **deps:** update dependency @netlify/plugin-edge-handlers to ^1.11.19 ([#2726](https://www.github.com/netlify/cli/issues/2726)) ([eff70a9](https://www.github.com/netlify/cli/commit/eff70a909d3a17010b96f9dabe6fb9a97aa9a62d))

### [3.37.38](https://www.github.com/netlify/cli/compare/v3.37.37...v3.37.38) (2021-06-21)


20 changes: 10 additions & 10 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "netlify-cli",
"description": "Netlify command line tool",
"version": "3.37.38",
"version": "3.38.0",
"author": "Netlify Inc.",
"contributors": [
"Mathias Biilmann <matt@netlify.com> (https://twitter.com/biilmann)",
@@ -78,7 +78,7 @@
"@netlify/build": "^12.2.0",
"@netlify/config": "^7.4.0",
"@netlify/framework-info": "^5.3.0",
"@netlify/plugin-edge-handlers": "^1.11.18",
"@netlify/plugin-edge-handlers": "^1.11.19",
"@netlify/plugins-list": "^2.16.0",
"@netlify/routing-local-proxy": "^0.30.1",
"@netlify/zip-it-and-ship-it": "^4.4.1",
2 changes: 1 addition & 1 deletion src/commands/dev/index.js
Original file line number Diff line number Diff line change
@@ -13,14 +13,14 @@ const waitPort = require('wait-port')
const which = require('which')
const wrapAnsi = require('wrap-ansi')

const { startFunctionsServer } = require('../../lib/functions/server')
const Command = require('../../utils/command')
const { serverSettings } = require('../../utils/detect-server')
const { getSiteInformation, injectEnvVariables } = require('../../utils/dev')
const { startLiveTunnel } = require('../../utils/live-tunnel')
const { NETLIFYDEV, NETLIFYDEVLOG, NETLIFYDEVWARN, NETLIFYDEVERR } = require('../../utils/logo')
const openBrowser = require('../../utils/open-browser')
const { startProxy } = require('../../utils/proxy')
const { startFunctionsServer } = require('../../utils/serve-functions')
const { startForwardProxy } = require('../../utils/traffic-mesh')

// 1 second
2 changes: 1 addition & 1 deletion src/commands/functions/serve.js
Original file line number Diff line number Diff line change
@@ -2,10 +2,10 @@ const { join } = require('path')

const { flags: flagsLib } = require('@oclif/command')

const { startFunctionsServer } = require('../../lib/functions/server')
const Command = require('../../utils/command')
const { getSiteInformation, acquirePort } = require('../../utils/dev')
const { getFunctionsDir } = require('../../utils/functions')
const { startFunctionsServer } = require('../../utils/serve-functions')

const DEFAULT_PORT = 9999

35 changes: 35 additions & 0 deletions src/lib/functions/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const lambdaLocal = require('lambda-local')

const { NETLIFYDEVERR, NETLIFYDEVLOG } = require('../../utils/logo')

const { DEFAULT_LAMBDA_OPTIONS, formatLambdaError, SECONDS_TO_MILLISECONDS, styleFunctionName } = require('./utils')

const BACKGROUND_FUNCTION_STATUS_CODE = 202

const createBackgroundFunctionCallback = (functionName) => (err) => {
if (err) {
console.log(
`${NETLIFYDEVERR} Error during background function ${styleFunctionName(functionName)} execution:`,
formatLambdaError(err),
)
} else {
console.log(`${NETLIFYDEVLOG} Done executing background function ${styleFunctionName(functionName)}`)
}
}

const executeBackgroundFunction = ({ event, lambdaPath, timeout, clientContext, response, functionName }) => {
console.log(`${NETLIFYDEVLOG} Queueing background function ${styleFunctionName(functionName)} for execution`)
response.status(BACKGROUND_FUNCTION_STATUS_CODE)
response.end()

return lambdaLocal.execute({
...DEFAULT_LAMBDA_OPTIONS,
event,
lambdaPath,
clientContext,
callback: createBackgroundFunctionCallback(functionName),
timeoutMs: timeout * SECONDS_TO_MILLISECONDS,
})
}

module.exports = { executeBackgroundFunction }
158 changes: 158 additions & 0 deletions src/lib/functions/builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
const { relative } = require('path')
const { cwd } = require('process')

const chalk = require('chalk')
const chokidar = require('chokidar')
const decache = require('decache')
const debounce = require('lodash/debounce')
const pEvent = require('p-event')

const { detectFunctionsBuilder } = require('../../utils/detect-functions-builder')
const { getFunctionsAndWatchDirs } = require('../../utils/get-functions')
const { NETLIFYDEVLOG } = require('../../utils/logo')

const { logBeforeAction, logAfterAction, validateFunctions } = require('./utils')

const DEBOUNCE_WAIT = 300

const clearCache =
({ action }) =>
(path) => {
logBeforeAction({ path, action })
decache(path)
logAfterAction({ path, action })
}

const getBuildFunction = ({ functionBuilder, log }) =>
async function build(updatedPath, eventType) {
const relativeFunctionsDir = relative(cwd(), functionBuilder.src)

log(`${NETLIFYDEVLOG} ${chalk.magenta('Building')} functions from directory ${chalk.yellow(relativeFunctionsDir)}`)

try {
const functions = await functionBuilder.build(updatedPath, eventType)
const functionNames = (functions || []).map((path) => relative(functionBuilder.src, path))

// If the build command has returned a set of functions that have been
// updated, the list them in the log message. If not, we show a generic
// message with the functions directory.
if (functionNames.length === 0) {
log(
`${NETLIFYDEVLOG} ${chalk.green('Finished')} building functions from directory ${chalk.yellow(
relativeFunctionsDir,
)}`,
)
} else {
log(
`${NETLIFYDEVLOG} ${chalk.green('Finished')} building functions: ${functionNames
.map((name) => chalk.yellow(name))
.join(', ')}`,
)
}
} catch (error) {
const errorMessage = (error.stderr && error.stderr.toString()) || error.message
log(
`${NETLIFYDEVLOG} ${chalk.red('Failed')} building functions from directory ${chalk.yellow(
relativeFunctionsDir,
)}${errorMessage ? ` with error:\n${errorMessage}` : ''}`,
)
}
}

const setupDefaultFunctionHandler = async ({ capabilities, directory, warn }) => {
const context = {
functions: [],
watchDirs: [],
}
const { functions, watchDirs } = await getFunctionsAndWatchDirs(directory)
const watcher = chokidar.watch(watchDirs, { ignored: /node_modules/, ignoreInitial: true })
await pEvent(watcher, 'ready')
const debouncedOnChange = debounce(clearCache({ action: 'modified' }), DEBOUNCE_WAIT, {
leading: false,
trailing: true,
})
const debouncedOnUnlink = debounce(
(path) => {
context.functions = context.functions.filter((func) => func.mainFile !== path)

clearCache({ action: 'deleted' })
},
DEBOUNCE_WAIT,
{
leading: false,
trailing: true,
},
)
const debouncedOnAdd = debounce(
async (path) => {
logBeforeAction({ path, action: 'added' })

if (context.watchDirs.length !== 0) {
await watcher.unwatch(watchDirs)
}

const { functions: newFunctions, watchDirs: newWatchDirs } = await getFunctionsAndWatchDirs(directory)

validateFunctions({ functions, capabilities, warn })

decache(path)

await watcher.add(newWatchDirs)

context.functions = newFunctions
context.watchDirs = newWatchDirs

logAfterAction({ path, action: 'added' })
},
DEBOUNCE_WAIT,
{ leading: false, trailing: true },
)

validateFunctions({ functions, capabilities, warn })

context.functions = functions
context.watchDirs = watchDirs

watcher.on('change', debouncedOnChange).on('unlink', debouncedOnUnlink).on('add', debouncedOnAdd)

const getFunctionByName = (functionName) => context.functions.find(({ name }) => name === functionName)

return { getFunctionByName }
}

const setupFunctionsBuilder = async ({ config, errorExit, functionsDirectory, log, site }) => {
const functionBuilder = await detectFunctionsBuilder({
config,
errorExit,
functionsDirectory,
log,
projectRoot: site.root,
})

if (!functionBuilder) {
return {}
}

const npmScriptString = functionBuilder.npmScript
? `: Running npm script ${chalk.yellow(functionBuilder.npmScript)}`
: ''

log(`${NETLIFYDEVLOG} Function builder ${chalk.yellow(functionBuilder.builderName)} detected${npmScriptString}.`)

const buildFunction = getBuildFunction({ functionBuilder, log })

await buildFunction()

const functionWatcher = chokidar.watch(functionBuilder.src)
await pEvent(functionWatcher, 'ready')
functionWatcher.on('add', (path) => buildFunction(path, 'add'))
functionWatcher.on('change', async (path) => {
await buildFunction(path, 'change')
decache(path)
})
functionWatcher.on('unlink', (path) => buildFunction(path, 'unlink'))

return functionBuilder
}

module.exports = { setupDefaultFunctionHandler, setupFunctionsBuilder }
Loading