diff --git a/packages/edge-bundler/src/manifest.ts b/packages/edge-bundler/src/manifest.ts index c8676cac63..bd3213b12a 100644 --- a/packages/edge-bundler/src/manifest.ts +++ b/packages/edge-bundler/src/manifest.ts @@ -30,7 +30,7 @@ const generateManifest = ({ bundles = [], declarations = [], functions }: Genera return } - const pattern = 'pattern' in declaration ? new RegExp(declaration.pattern) : globToRegExp(declaration.path) + const pattern = getRegularExpression(declaration) const serializablePattern = pattern.source.replace(/\\\//g, '/') return { @@ -51,6 +51,23 @@ const generateManifest = ({ bundles = [], declarations = [], functions }: Genera return manifest } +const getRegularExpression = (declaration: Declaration) => { + if ('pattern' in declaration) { + return new RegExp(declaration.pattern) + } + + // We use the global flag so that `globToRegExp` will not wrap the expression + // with `^` and `$`. We'll do that ourselves. + const regularExpression = globToRegExp(declaration.path, { flags: 'g' }) + + // Wrapping the expression source with `^` and `$`. Also, adding an optional + // trailing slash, so that a declaration of `path: "/foo"` matches requests + // for both `/foo` and `/foo/`. + const normalizedSource = `^${regularExpression.source}\\/?$` + + return new RegExp(normalizedSource) +} + interface WriteManifestOptions { bundles: Bundle[] declarations: Declaration[] diff --git a/packages/edge-bundler/test/manifest.ts b/packages/edge-bundler/test/manifest.ts index be71da1726..e1cb66308d 100644 --- a/packages/edge-bundler/test/manifest.ts +++ b/packages/edge-bundler/test/manifest.ts @@ -23,7 +23,7 @@ test('Generates a manifest with different bundles', (t) => { { asset: bundle1.hash + bundle1.extension, format: bundle1.format }, { asset: bundle2.hash + bundle2.extension, format: bundle2.format }, ] - const expectedRoutes = [{ function: 'func-1', pattern: '^/f1$' }] + const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$' }] t.deepEqual(manifest.bundles, expectedBundles) t.deepEqual(manifest.routes, expectedRoutes) @@ -43,7 +43,7 @@ test('Excludes functions for which there are function files but no matching conf const declarations = [{ function: 'func-1', path: '/f1' }] const manifest = generateManifest({ bundles: [bundle1], declarations, functions }) - const expectedRoutes = [{ function: 'func-1', pattern: '^/f1$' }] + const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$' }] t.deepEqual(manifest.routes, expectedRoutes) }) @@ -61,7 +61,7 @@ test('Excludes functions for which there are config declarations but no matching ] const manifest = generateManifest({ bundles: [bundle1], declarations, functions }) - const expectedRoutes = [{ function: 'func-2', pattern: '^/f2$' }] + const expectedRoutes = [{ function: 'func-2', pattern: '^/f2/?$' }] t.deepEqual(manifest.routes, expectedRoutes) }) @@ -71,7 +71,7 @@ test('Generates a manifest without bundles', (t) => { const declarations = [{ function: 'func-1', path: '/f1' }] const manifest = generateManifest({ bundles: [], declarations, functions }) - const expectedRoutes = [{ function: 'func-1', pattern: '^/f1$' }] + const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$' }] t.deepEqual(manifest.bundles, []) t.deepEqual(manifest.routes, expectedRoutes)