Skip to content

Commit

Permalink
feat: warn about orphaned Edge Function declarations (#4554)
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardoboucas authored Apr 20, 2022
1 parent 9998550 commit 8945228
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
32 changes: 21 additions & 11 deletions src/lib/edge-functions/proxy.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// @ts-check
const { env } = require('process')
const { relative } = require('path')
const { cwd, env } = require('process')

const getAvailablePort = require('get-port')
const { v4: generateUUID } = require('uuid')

const { NETLIFYDEVERR, chalk } = require('../../utils/command-helpers')
const { NETLIFYDEVERR, NETLIFYDEVWARN, chalk, log } = require('../../utils/command-helpers')
const { getPathInProject } = require('../settings')
const { startSpinner, stopSpinner } = require('../spinner')

Expand Down Expand Up @@ -69,20 +70,29 @@ const initializeProxy = async ({ config, configPath, getUpdatedConfig, settings

await registry.initialize()

const manifest = await registry.getManifest()
const url = new URL(req.url, `http://${LOCAL_HOST}:${mainPort}`)
const routes = manifest.routes.map((route) => ({
...route,
pattern: new RegExp(route.pattern),
}))
const matchingFunctions = routes.filter(({ pattern }) => pattern.test(url.pathname)).map((route) => route.function)

if (matchingFunctions.length === 0) {
const { functionNames, orphanedDeclarations } = await registry.matchURLPath(url.pathname)

// If the request matches a config declaration for an Edge Function without
// a matching function file, we warn the user.
orphanedDeclarations.forEach((functionName) => {
log(
`${NETLIFYDEVWARN} Request to ${chalk.yellow(
url.pathname,
)} matches declaration for edge function ${chalk.yellow(
functionName,
)}, but there's no matching function file in ${chalk.yellow(
relative(cwd(), userFunctionsPath),
)}. Please visit ${chalk.blue('https://ntl.fyi/edge-create')} for more information.`,
)
})

if (functionNames.length === 0) {
return
}

req[headersSymbol] = {
[headers.Functions]: matchingFunctions.join(','),
[headers.Functions]: functionNames.join(','),
[headers.PassHost]: `${LOCAL_HOST}:${mainPort}`,
[headers.Passthrough]: 'passthrough',
[headers.RequestID]: generateUUID(),
Expand Down
39 changes: 39 additions & 0 deletions src/lib/edge-functions/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,45 @@ class EdgeFunctionsRegistry {
log(`${NETLIFYDEVLOG} ${chalk.magenta('Removed')} edge function ${chalk.yellow(func.name)}`)
}

/**
* @param {string} urlPath
*/
async matchURLPath(urlPath) {
// `generateManifest` will only include functions for which there is both a
// function file and a config declaration, but we want to catch cases where
// a config declaration exists without a matching function file. To do that
// we compute a list of functions from the declarations (the `path` doesn't
// really matter) and later on match the resulting routes against the list
// of functions we have in the registry. Any functions found in the former
// but not the latter are treated as orphaned declarations.
const functions = this.declarations.map((declaration) => ({ name: declaration.function, path: '' }))
const manifest = await this.bundler.generateManifest({
declarations: this.declarations,
functions,
})
const routes = manifest.routes.map((route) => ({
...route,
pattern: new RegExp(route.pattern),
}))
const orphanedDeclarations = new Set()
const functionNames = routes
.filter(({ pattern }) => pattern.test(urlPath))
.map((route) => {
const matchingFunction = this.functions.find(({ name }) => name === route.function)

if (matchingFunction === undefined) {
orphanedDeclarations.add(route.function)

return null
}

return matchingFunction.name
})
.filter(Boolean)

return { functionNames, orphanedDeclarations }
}

processGraph(graph) {
if (!graph) {
warn('Could not process edge functions dependency graph. Live reload will not be available.')
Expand Down

1 comment on commit 8945228

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📊 Benchmark results

Package size: 273 MB

Please sign in to comment.