Skip to content

Commit

Permalink
feat: support 'pattern' in inline edge function config
Browse files Browse the repository at this point in the history
  • Loading branch information
pieh committed Jul 2, 2024
1 parent 2f312cb commit 743405c
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 29 deletions.
19 changes: 16 additions & 3 deletions packages/edge-bundler/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,30 @@ export const isValidOnError = (value: unknown): value is OnError => {
return value === 'fail' || value === 'bypass' || value.startsWith('/')
}

export interface FunctionConfig {
interface BaseFunctionConfig {
cache?: Cache
path?: Path | Path[]
excludedPath?: Path | Path[]
onError?: OnError
name?: string
generator?: string
method?: HTTPMethod | HTTPMethod[]
rateLimit?: RateLimit
}

interface FunctionConfigWithPath extends BaseFunctionConfig {
path?: Path | Path[]
excludedPath?: Path | Path[]
}

interface FunctionConfigWithPattern extends BaseFunctionConfig {
pattern: string | string[]
excludedPattern?: string | string[]
}

export type FunctionConfig = FunctionConfigWithPath | FunctionConfigWithPattern

export type FunctionConfigWithAllPossibleFields = BaseFunctionConfig &
Partial<FunctionConfigWithPath & FunctionConfigWithPattern>

const getConfigExtractor = () => {
const packagePath = getPackagePath()
const configExtractorPath = join(packagePath, 'deno', 'config.ts')
Expand Down
66 changes: 47 additions & 19 deletions packages/edge-bundler/node/declaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,15 @@ const getDeclarationsFromInput = (
if (!config) {
// If no config is found, add the declaration as is.
declarations.push(declaration)
} else if (config.path?.length) {
} else if ('pattern' in config && config.pattern?.length) {
// If we have a pattern specified as either a string or non-empty array,
// create a declaration for each pattern.
const patterns = Array.isArray(config.pattern) ? config.pattern : [config.pattern]

patterns.forEach((pattern) => {
declarations.push({ ...declaration, cache: config.cache, pattern })
})
} else if ('path' in config && config.path?.length) {
// If we have a path specified as either a string or non-empty array,
// create a declaration for each path.
const paths = Array.isArray(config.path) ? config.path : [config.path]
Expand All @@ -74,7 +82,7 @@ const getDeclarationsFromInput = (
} else {
// With an in-source config without a path, add the config to the declaration.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { path, excludedPath, ...rest } = config
const { path, excludedPath, pattern, excludedPattern, ...rest } = config as FunctionConfigWithAllPossibleFields

declarations.push({ ...declaration, ...rest })
}
Expand All @@ -92,25 +100,45 @@ const createDeclarationsFromFunctionConfigs = (
const declarations: Declaration[] = []

for (const name in functionConfigs) {
const { cache, excludedPath, path, method } = functionConfigs[name]
const functionConfig = functionConfigs[name]
const { cache, method } = functionConfigs[name]

// If we have a path specified, create a declaration for each path.
if (!functionsVisited.has(name) && path) {
const paths = Array.isArray(path) ? path : [path]

paths.forEach((singlePath) => {
const declaration: Declaration = { function: name, path: singlePath }
if (cache) {
declaration.cache = cache
}
if (method) {
declaration.method = method
}
if (excludedPath) {
declaration.excludedPath = excludedPath
}
declarations.push(declaration)
})
if (!functionsVisited.has(name)) {
if ('pattern' in functionConfig && functionConfig.pattern) {
const { pattern, excludedPattern } = functionConfig
const patterns = Array.isArray(pattern) ? pattern : [pattern]
patterns.forEach((singlePattern) => {
const declaration: Declaration = { function: name, pattern: singlePattern }
if (cache) {
declaration.cache = cache
}
if (method) {
declaration.method = method
}
if (excludedPattern) {
declaration.excludedPattern = excludedPattern
}
declarations.push(declaration)
})
} else if ('path' in functionConfig && functionConfig.path) {
const { path, excludedPath } = functionConfig
const paths = Array.isArray(path) ? path : [path]

paths.forEach((singlePath) => {
const declaration: Declaration = { function: name, path: singlePath }
if (cache) {
declaration.cache = cache
}
if (method) {
declaration.method = method
}
if (excludedPath) {
declaration.excludedPath = excludedPath
}
declarations.push(declaration)
})
}
}
}

Expand Down
41 changes: 34 additions & 7 deletions packages/edge-bundler/node/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { join } from 'path'

import type { Bundle } from './bundle.js'
import { wrapBundleError } from './bundle_error.js'
import { Cache, FunctionConfig, Path } from './config.js'
import { Cache, FunctionConfig, FunctionConfigWithAllPossibleFields, Path } from './config.js'
import { Declaration, normalizePattern } from './declaration.js'
import { EdgeFunction } from './edge_function.js'
import { FeatureFlags } from './feature_flags.js'
Expand Down Expand Up @@ -97,7 +97,7 @@ const sanitizeEdgeFunctionConfig = (config: Record<string, EdgeFunctionConfig>):
return newConfig
}

const addExcludedPatterns = (
const addManifestExcludedPatternsFromConfigExcludedPath = (
name: string,
manifestFunctionConfig: Record<string, EdgeFunctionConfig>,
excludedPath?: Path | Path[],
Expand All @@ -110,6 +110,19 @@ const addExcludedPatterns = (
}
}

const addManifestExcludedPatternsFromConfigExcludedPattern = (
name: string,
manifestFunctionConfig: Record<string, EdgeFunctionConfig>,
excludedPattern?: string | string[],
) => {
if (excludedPattern) {
const excludedPatterns = Array.isArray(excludedPattern) ? excludedPattern : [excludedPattern]
const normalizedExcludedPatterns = excludedPatterns.filter(nonNullable).map(normalizePattern).map(serializePattern)

manifestFunctionConfig[name].excluded_patterns.push(...normalizedExcludedPatterns)
}
}

/**
* Normalizes method names into arrays of uppercase strings.
* (e.g. "get" becomes ["GET"])
Expand Down Expand Up @@ -144,13 +157,20 @@ const generateManifest = ({
const routedFunctions = new Set<string>()
const declarationsWithoutFunction = new Set<string>()

for (const [name, { excludedPath, onError, rateLimit }] of Object.entries(userFunctionConfig)) {
for (const [name, singleUserFunctionConfig] of Object.entries(userFunctionConfig)) {
// If the config block is for a function that is not defined, discard it.
if (manifestFunctionConfig[name] === undefined) {
continue
}

addExcludedPatterns(name, manifestFunctionConfig, excludedPath)
const { excludedPath, pattern, excludedPattern, onError, rateLimit } =
singleUserFunctionConfig as FunctionConfigWithAllPossibleFields

if (pattern && excludedPattern) {
addManifestExcludedPatternsFromConfigExcludedPattern(name, manifestFunctionConfig, excludedPattern)
} else {
addManifestExcludedPatternsFromConfigExcludedPath(name, manifestFunctionConfig, excludedPath)
}

manifestFunctionConfig[name] = {
...manifestFunctionConfig[name],
Expand All @@ -159,14 +179,21 @@ const generateManifest = ({
}
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [name, { excludedPath, path, onError, rateLimit, ...rest }] of Object.entries(internalFunctionConfig)) {
for (const [name, singleInternalFunctionConfig] of Object.entries(internalFunctionConfig)) {
// If the config block is for a function that is not defined, discard it.
if (manifestFunctionConfig[name] === undefined) {
continue
}

addExcludedPatterns(name, manifestFunctionConfig, excludedPath)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { onError, rateLimit, path, excludedPath, pattern, excludedPattern, ...rest } =
singleInternalFunctionConfig as FunctionConfigWithAllPossibleFields

if (pattern && excludedPattern) {
addManifestExcludedPatternsFromConfigExcludedPattern(name, manifestFunctionConfig, excludedPattern)
} else {
addManifestExcludedPatternsFromConfigExcludedPath(name, manifestFunctionConfig, excludedPath)
}

manifestFunctionConfig[name] = {
...manifestFunctionConfig[name],
Expand Down

0 comments on commit 743405c

Please sign in to comment.