Skip to content

Commit

Permalink
feat: add support for post-cache routes (#165)
Browse files Browse the repository at this point in the history
* feat: add support for post-cache routes

* refactor: rename `mode` values
  • Loading branch information
eduardoboucas committed Oct 20, 2022
1 parent 8e5ab76 commit c7e530b
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 12 deletions.
12 changes: 8 additions & 4 deletions node/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ test('Ignores function paths from the in-source `config` function if the feature
})
const generatedFiles = await fs.readdir(tmpDir.path)

expect(result.functions.length).toBe(4)
expect(result.functions.length).toBe(6)
expect(generatedFiles.length).toBe(2)

const manifestFile = await fs.readFile(resolve(tmpDir.path, 'manifest.json'), 'utf8')
Expand Down Expand Up @@ -197,22 +197,26 @@ test('Loads function paths from the in-source `config` function', async () => {
})
const generatedFiles = await fs.readdir(tmpDir.path)

expect(result.functions.length).toBe(4)
expect(result.functions.length).toBe(6)
expect(generatedFiles.length).toBe(2)

const manifestFile = await fs.readFile(resolve(tmpDir.path, 'manifest.json'), 'utf8')
const manifest = JSON.parse(manifestFile)
const { bundles, routes } = manifest
const { bundles, routes, post_cache_routes: postCacheRoutes } = manifest

expect(bundles.length).toBe(1)
expect(bundles[0].format).toBe('eszip2')
expect(generatedFiles.includes(bundles[0].asset)).toBe(true)

expect(routes.length).toBe(4)
expect(routes.length).toBe(5)
expect(routes[0]).toEqual({ function: 'framework-func2', pattern: '^/framework-func2/?$' })
expect(routes[1]).toEqual({ function: 'user-func2', pattern: '^/user-func2/?$' })
expect(routes[2]).toEqual({ function: 'framework-func1', pattern: '^/framework-func1/?$' })
expect(routes[3]).toEqual({ function: 'user-func1', pattern: '^/user-func1/?$' })
expect(routes[4]).toEqual({ function: 'user-func3', pattern: '^/user-func3/?$' })

expect(postCacheRoutes.length).toBe(1)
expect(postCacheRoutes[0]).toEqual({ function: 'user-func4', pattern: '^/user-func4/?$' })

await fs.rmdir(tmpDir.path, { recursive: true })
})
7 changes: 7 additions & 0 deletions node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ enum ConfigExitCode {
SerializationError,
}

// eslint-disable-next-line no-shadow
export const enum Mode {
BeforeCache = 'before-cache',
AfterCache = 'after-cache',
}

export interface FunctionConfig {
mode?: Mode
path?: string
}

Expand Down
7 changes: 4 additions & 3 deletions node/declaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FunctionConfig } from './config.js'

interface BaseDeclaration {
function: string
mode?: string
name?: string
}

Expand Down Expand Up @@ -31,7 +32,7 @@ export const getDeclarationsFromConfig = (
if (path) {
functionsVisited.add(declaration.function)

declarations.push({ function: declaration.function, path })
declarations.push({ ...declaration, path })
} else {
declarations.push(declaration)
}
Expand All @@ -40,10 +41,10 @@ export const getDeclarationsFromConfig = (
// Finally, we must create declarations for functions that are not declared
// in the TOML at all.
for (const name in functionsConfig) {
const { path } = functionsConfig[name]
const { path, ...config } = functionsConfig[name]

if (!functionsVisited.has(name) && path) {
declarations.push({ function: name, path })
declarations.push({ ...config, function: name, path })
}
}

Expand Down
39 changes: 39 additions & 0 deletions node/manifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,42 @@ test('Generates a manifest without bundles', () => {
expect(manifest.routes).toEqual(expectedRoutes)
expect(manifest.bundler_version).toBe(env.npm_package_version as string)
})

test('Generates a manifest with pre and post-cache routes', () => {
const bundle1 = {
extension: '.ext1',
format: 'format1',
hash: '123456',
}
const bundle2 = {
extension: '.ext2',
format: 'format2',
hash: '654321',
}
const functions = [
{ name: 'func-1', path: '/path/to/func-1.ts' },
{ name: 'func-2', path: '/path/to/func-2.ts' },
{ name: 'func-3', path: '/path/to/func-3.ts' },
]
const declarations = [
{ function: 'func-1', path: '/f1' },
{ function: 'func-2', mode: 'not_a_supported_mode', path: '/f2' },
{ function: 'func-3', mode: 'after-cache', path: '/f3' },
]
const manifest = generateManifest({ bundles: [bundle1, bundle2], declarations, functions })

const expectedBundles = [
{ asset: bundle1.hash + bundle1.extension, format: bundle1.format },
{ asset: bundle2.hash + bundle2.extension, format: bundle2.format },
]
const expectedPreCacheRoutes = [
{ function: 'func-1', name: undefined, pattern: '^/f1/?$' },
{ function: 'func-2', name: undefined, pattern: '^/f2/?$' },
]
const expectedPostCacheRoutes = [{ function: 'func-3', name: undefined, pattern: '^/f3/?$' }]

expect(manifest.bundles).toEqual(expectedBundles)
expect(manifest.routes).toEqual(expectedPreCacheRoutes)
expect(manifest.post_cache_routes).toEqual(expectedPostCacheRoutes)
expect(manifest.bundler_version).toBe(env.npm_package_version as string)
})
28 changes: 23 additions & 5 deletions node/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { join } from 'path'
import globToRegExp from 'glob-to-regexp'

import type { Bundle } from './bundle.js'
import { Mode } from './config.js'
import type { Declaration } from './declaration.js'
import { EdgeFunction } from './edge_function.js'
import { getPackageVersion } from './package_json.js'
Expand All @@ -15,15 +16,26 @@ interface GenerateManifestOptions {
declarations?: Declaration[]
}

/* eslint-disable camelcase */
interface Manifest {
// eslint-disable-next-line camelcase
bundler_version: string
bundles: { asset: string; format: string }[]
routes: { function: string; name?: string; pattern: string }[]
post_cache_routes: { function: string; name?: string; pattern: string }[]
}
/* eslint-enable camelcase */

interface Route {
function: string
name?: string
pattern: string
}

const generateManifest = ({ bundles = [], declarations = [], functions }: GenerateManifestOptions) => {
const routes = declarations.map((declaration) => {
const preCacheRoutes: Route[] = []
const postCacheRoutes: Route[] = []

declarations.forEach((declaration) => {
const func = functions.find(({ name }) => declaration.function === name)

if (func === undefined) {
Expand All @@ -32,20 +44,26 @@ const generateManifest = ({ bundles = [], declarations = [], functions }: Genera

const pattern = getRegularExpression(declaration)
const serializablePattern = pattern.source.replace(/\\\//g, '/')

return {
const route = {
function: func.name,
name: declaration.name,
pattern: serializablePattern,
}

if (declaration.mode === Mode.AfterCache) {
postCacheRoutes.push(route)
} else {
preCacheRoutes.push(route)
}
})
const manifestBundles = bundles.map(({ extension, format, hash }) => ({
asset: hash + extension,
format,
}))
const manifest: Manifest = {
bundles: manifestBundles,
routes: routes.filter(nonNullable),
routes: preCacheRoutes.filter(nonNullable),
post_cache_routes: postCacheRoutes.filter(nonNullable),
bundler_version: getPackageVersion(),
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default async () => new Response('Hello from user function 3')

export const config = () => ({
mode: 'not_a_supported_mode',
path: '/user-func3',
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default async () => new Response('Hello from user function 4. I should run after the cache!')

export const config = () => ({
mode: 'after-cache',
path: '/user-func4',
})

0 comments on commit c7e530b

Please sign in to comment.