Skip to content

Commit

Permalink
Merge 67a3235 into 32becb3
Browse files Browse the repository at this point in the history
  • Loading branch information
estrattonbailey committed Feb 19, 2022
2 parents 32becb3 + 67a3235 commit 3ab4afb
Show file tree
Hide file tree
Showing 20 changed files with 277 additions and 125 deletions.
9 changes: 9 additions & 0 deletions .changeset/breezy-cheetahs-thank.md
@@ -0,0 +1,9 @@
---
'@presta/adapter-cloudflare-workers': minor
'@presta/adapter-netlify': minor
'@presta/adapter-node': minor
'@presta/adapter-vercel': minor
'presta': minor
---

Output and consume manifest.json
17 changes: 9 additions & 8 deletions packages/adapter-cloudflare-workers/lib/index.ts
@@ -1,7 +1,7 @@
import fs from 'fs'
import path from 'path'
import { mkdir } from 'mk-dirs/sync'
import { createPlugin, logger, HookPostBuildPayload, Config } from 'presta'
import { createPlugin, logger, HookPostBuildPayload, Config, getDynamicFilesFromManifest } from 'presta'
import { build as esbuild } from 'esbuild'
import { timer } from '@presta/utils/timer'
import { requireSafe } from '@presta/utils/requireSafe'
Expand Down Expand Up @@ -51,19 +51,20 @@ export function getWranglerConfig() {
}

export async function onPostBuild(props: HookPostBuildPayload) {
const { output, functionsManifest: fns } = props
const { output, manifest } = props
const filepath = path.join(output, 'worker.js')

mkdir(output)

const imports = Object.entries(fns)
.map(([route, filepath]) => {
return `import * as ${slugify(filepath)} from "${filepath}"`
const dynamicFiles = getDynamicFilesFromManifest(manifest)
const imports = dynamicFiles
.map((file) => {
return `import * as ${slugify(file.dest)} from "${file.dest}"`
})
.join(';\n')
const runtime = Object.entries(fns)
.map(([route, filepath]) => {
return `routes.push({ route: "${route}", module: ${slugify(filepath)} })`
const runtime = dynamicFiles
.map((file) => {
return `routes.push({ route: "${file.route}", module: ${slugify(file.dest)} })`
})
.join(';\n')

Expand Down
46 changes: 40 additions & 6 deletions packages/adapter-netlify/__tests__/index.ts
Expand Up @@ -3,6 +3,7 @@ import path from 'path'
import { suite } from 'uvu'
import * as assert from 'uvu/assert'
import { afix } from 'afix'
import { ManifestDynamicFile } from 'presta'

import createPlugin, {
toAbsolutePath,
Expand All @@ -29,7 +30,13 @@ test('normalizeNetlifyRoute', async () => {
})

test('prestaRoutesToNetlifyRedirects', async () => {
assert.equal(prestaRoutesToNetlifyRedirects([['*', 'Func']])[0], {
const dynamicFile: ManifestDynamicFile = {
type: 'dynamic',
src: 'src',
dest: 'Func',
route: '/*',
}
assert.equal(prestaRoutesToNetlifyRedirects([dynamicFile])[0], {
from: '/*',
to: '/.netlify/functions/Func',
status: 200,
Expand Down Expand Up @@ -171,7 +178,7 @@ test('onPostBuild - just static, netlify config matches presta config', async ()
output: path.join(fixtures.root, 'build'),
staticOutput: path.join(fixtures.root, 'build/static'),
functionsOutput: path.join(fixtures.root, 'build/functions'),
functionsManifest: {},
manifest: { files: [] },
}

await onPostBuild(config, props)
Expand All @@ -196,7 +203,7 @@ test('onPostBuild - just static, netlify config does not match presta config', a
output: path.join(fixtures.root, 'build'),
staticOutput: path.join(fixtures.root, 'build/static'),
functionsOutput: path.join(fixtures.root, 'build/functions'),
functionsManifest: {},
manifest: { files: [] },
}

await onPostBuild(config, props)
Expand All @@ -221,7 +228,16 @@ test('onPostBuild - has functions, not configured', async () => {
output: path.join(fixtures.root, 'build'),
staticOutput: path.join(fixtures.root, 'build/static'),
functionsOutput: path.join(fixtures.root, 'build/functions'),
functionsManifest: { '*': fixtures.files.lambda.path },
manifest: {
files: [
{
type: 'dynamic',
src: 'src',
dest: fixtures.files.lambda.path,
route: '*',
} as ManifestDynamicFile,
],
},
}

let plan = 0
Expand Down Expand Up @@ -256,7 +272,16 @@ test(`onPostBuild - has functions, paths match`, async () => {
output: path.join(fixtures.root, 'build'),
staticOutput: path.join(fixtures.root, 'build/static'),
functionsOutput: path.join(fixtures.root, 'build/functions'),
functionsManifest: { '*': fixtures.files.lambda.path },
manifest: {
files: [
{
type: 'dynamic',
src: 'src',
dest: fixtures.files.lambda.path,
route: '*',
} as ManifestDynamicFile,
],
},
}

await onPostBuild(config, props)
Expand Down Expand Up @@ -289,7 +314,16 @@ test(`onPostBuild - has functions, paths don't match`, async () => {
output: path.join(fixtures.root, 'build'),
staticOutput: path.join(fixtures.root, 'build/static'),
functionsOutput: path.join(fixtures.root, 'build/functions'),
functionsManifest: { '*': fixtures.files.lambda.path },
manifest: {
files: [
{
type: 'dynamic',
src: 'src',
dest: fixtures.files.lambda.path,
route: '*',
} as ManifestDynamicFile,
],
},
}

await onPostBuild(config, props)
Expand Down
14 changes: 7 additions & 7 deletions packages/adapter-netlify/index.ts
Expand Up @@ -3,7 +3,7 @@ import fs from 'fs-extra'
import path from 'path'
import { premove } from 'premove/sync'
import { mkdir } from 'mk-dirs/sync'
import { createPlugin, logger, HookPostBuildPayload } from 'presta'
import { createPlugin, logger, HookPostBuildPayload, ManifestDynamicFile, getDynamicFilesFromManifest } from 'presta'
import { parse as toml } from 'toml'
// @ts-ignore
import { parseFileRedirects } from 'netlify-redirect-parser'
Expand Down Expand Up @@ -62,10 +62,10 @@ export function normalizeNetlifyRoute(route: string) {
return route
}

export function prestaRoutesToNetlifyRedirects(routes: [string, string][]): NetlifyRedirect[] {
return routes.map(([route, filename]) => ({
from: normalizeNetlifyRoute(route),
to: `/.netlify/functions/${path.basename(filename, '.js')}`,
export function prestaRoutesToNetlifyRedirects(files: ManifestDynamicFile[]): NetlifyRedirect[] {
return files.map((file) => ({
from: normalizeNetlifyRoute(file.route),
to: `/.netlify/functions/${path.basename(file.dest, '.js')}`,
status: 200,
force: false,
query: {},
Expand All @@ -91,7 +91,7 @@ export async function getUserConfiguredRedirects(dir: string) {
}

export async function onPostBuild(config: NetlifyConfig, props: HookPostBuildPayload) {
const { output, staticOutput, functionsOutput, functionsManifest } = props
const { output, staticOutput, functionsOutput, manifest } = props
const hasFunctions = fs.existsSync(functionsOutput)
const shouldCopyStaticFiles = config.build.publish !== staticOutput && fs.existsSync(staticOutput)
const shouldCopyFunctions = config.build.functions !== functionsOutput && hasFunctions
Expand All @@ -118,7 +118,7 @@ export async function onPostBuild(config: NetlifyConfig, props: HookPostBuildPay
if (shouldCopyFunctions) fs.copySync(functionsOutput, config.build.functions as string)

if (hasFunctions) {
const prestaRedirects = prestaRoutesToNetlifyRedirects(Object.entries(functionsManifest))
const prestaRedirects = prestaRoutesToNetlifyRedirects(getDynamicFilesFromManifest(manifest))
const combinedRedirects = userConfiguredRedirects.concat(prestaRedirects)
const redirectsFilepath = path.join(config.build.publish, '_redirects')

Expand Down
11 changes: 9 additions & 2 deletions packages/adapter-node/lib/__tests__/adapter.ts
Expand Up @@ -50,8 +50,15 @@ test('adapter', async () => {
adapter(
{
staticOutput: path.join(fixture.root, 'build/static'),
functionsManifest: {
[route]: fixture.files.fn.path,
manifest: {
files: [
{
type: 'dynamic',
src: 'src',
dest: fixture.files.fn.path,
route,
},
],
},
},
{ port: 4000 }
Expand Down
9 changes: 5 additions & 4 deletions packages/adapter-node/lib/adapter.ts
Expand Up @@ -8,18 +8,19 @@ import sirv from 'sirv'
import { Handler } from 'lambda-types'
import { requestToEvent } from '@presta/utils/requestToEvent'
import { sendServerlessResponse } from '@presta/utils/sendServerlessResponse'
import { HookPostBuildPayload } from 'presta'
import { HookPostBuildPayload, getDynamicFilesFromManifest } from 'presta'

import { Options } from './types'

export function adapter(props: HookPostBuildPayload, options: Options) {
const assets = sirv(path.resolve(__dirname, props.staticOutput))
const app = polka().use(assets)
const dynamicFiles = getDynamicFilesFromManifest(props.manifest)

for (const route in props.functionsManifest) {
app.all(route, async (req, res) => {
for (const file of dynamicFiles) {
app.all(file.route, async (req, res) => {
const event = await requestToEvent(req)
const { handler } = require(props.functionsManifest[route]) as { handler: Handler }
const { handler } = require(file.dest) as { handler: Handler }
// @ts-ignore
const response = await handler(event, {})
// @ts-ignore
Expand Down
23 changes: 17 additions & 6 deletions packages/adapter-vercel/lib/__tests__/index.ts
Expand Up @@ -4,6 +4,7 @@ import { suite } from 'uvu'
import * as assert from 'uvu/assert'
import { afix } from 'afix'
import { build as esbuild } from 'esbuild'
import { ManifestDynamicFile } from 'presta'

import createPlugin, { vercelConfig, onPostBuild } from '../index'

Expand All @@ -23,7 +24,7 @@ test('onPostBuild', async () => {
output,
staticOutput: path.join(output, 'static'),
functionsOutput: path.join(output, 'functions'),
functionsManifest: {},
manifest: { files: [] },
})

assert.ok(fs.existsSync(path.join(fixture.root, './.output/static/index.html')))
Expand Down Expand Up @@ -77,10 +78,20 @@ test('generateRoutes', async () => {
process.chdir(fixture.root)

const prestaOutput = path.join(fixture.root, 'build')
const prestaFunctionsManifest = {
'/': path.join(prestaOutput, 'functions/home.js'),
'*': path.join(prestaOutput, 'functions/page.js'),
}
const dynamicFiles: ManifestDynamicFile[] = [
{
type: 'dynamic',
src: 'src',
dest: path.join(prestaOutput, 'functions/home.js'),
route: '/',
},
{
type: 'dynamic',
src: 'src',
dest: path.join(prestaOutput, 'functions/page.js'),
route: '*',
},
]

const { generateRoutes } = require('proxyquire')('../index', {
esbuild: {
Expand All @@ -93,7 +104,7 @@ test('generateRoutes', async () => {
},
})

await generateRoutes(prestaOutput, prestaFunctionsManifest)
await generateRoutes(prestaOutput, dynamicFiles)

const routesManifestPath = path.join(process.cwd(), './.output/routes-manifest.json')
const routesManifest = JSON.parse(fs.readFileSync(routesManifestPath, 'utf8'))
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-vercel/lib/adapter.ts
Expand Up @@ -5,7 +5,7 @@
import { parse as parseUrl } from 'url'
import { NextApiRequest, NextApiResponse } from 'next'
import { Response } from 'lambda-types'
import { Handler, Event, Context } from 'presta'
import type { Handler, Event, Context } from 'presta'
import { normalizeHeaders } from '@presta/utils/normalizeHeaders'
import { parseQueryStringParameters } from '@presta/utils/parseQueryStringParameters'
import { sendServerlessResponse } from '@presta/utils/sendServerlessResponse'
Expand Down
19 changes: 10 additions & 9 deletions packages/adapter-vercel/lib/index.ts
Expand Up @@ -2,7 +2,7 @@ import fs from 'fs-extra'
import path from 'path'
import merge from 'deep-extend'
import toRegExp from 'regexparam'
import { createPlugin, logger, HookPostBuildPayload } from 'presta'
import { createPlugin, logger, HookPostBuildPayload, ManifestDynamicFile, getDynamicFilesFromManifest } from 'presta'
import { build as esbuild } from 'esbuild'
import { requireSafe } from '@presta/utils'

Expand Down Expand Up @@ -31,20 +31,19 @@ export const routesManifest: {

export async function generateRoutes(
prestaOutput: HookPostBuildPayload['output'],
prestaFunctionsManifest: HookPostBuildPayload['functionsManifest']
dynamicFiles: ManifestDynamicFile[]
) {
const manifest = Object.assign({}, routesManifest)

for (const route of Object.keys(prestaFunctionsManifest)) {
const source = prestaFunctionsManifest[route]
const filename = /^\/$/.test(route) ? 'index' : path.basename(source, '.js')
for (const source of dynamicFiles) {
const filename = /^\/$/.test(source.route) ? 'index' : path.basename(source.dest, '.js')
const tmpfile = path.join(prestaOutput, './.vercel', filename + '.js')
const { pattern } = toRegExp(route)
const { pattern } = toRegExp(source.route)

fs.outputFileSync(
tmpfile,
`import { adapter } from '@presta/adapter-vercel/dist/adapter';
import { handler } from '${source}';
import { handler } from '${source.dest}';
export default adapter(handler);`
)

Expand Down Expand Up @@ -78,10 +77,12 @@ export function mergeVercelConfig() {
}

export async function onPostBuild(props: HookPostBuildPayload) {
const { output: prestaOutput, staticOutput, functionsManifest } = props
const { output: prestaOutput, staticOutput, manifest } = props

fs.copySync(staticOutput, path.join(process.cwd(), './.output/static'))
if (Object.keys(functionsManifest).length) await generateRoutes(prestaOutput, functionsManifest)

const dynamicFiles = getDynamicFilesFromManifest(manifest)
if (dynamicFiles.length) await generateRoutes(prestaOutput, dynamicFiles)

logger.info({
label: '@presta/adapter-vercel',
Expand Down
2 changes: 1 addition & 1 deletion packages/presta/lib/__tests__/config.ts
Expand Up @@ -104,7 +104,7 @@ test('create', async () => {
plugins: [],
staticOutputDir: path.join(output, 'static'),
functionsOutputDir: path.join(output, 'functions'),
functionsManifest: path.join(output, 'routes.json'),
manifestFilepath: path.join(output, 'manifest.json'),
}

assert.equal(config, generated)
Expand Down
19 changes: 7 additions & 12 deletions packages/presta/lib/__tests__/outputLambdas.ts
Expand Up @@ -33,16 +33,11 @@ test('outputLambdas', async () => {
config
)

assert.equal(slug[0], `/:slug`)
assert.ok(slug[1].includes(`slug.js`))
assert.equal(slug.route, `/:slug`)
assert.ok(slug.dest.includes(`slug.js`))

assert.equal(fallback[0], `/:slug?`)
assert.ok(fallback[1].includes(`fallback.js`))

const manifest = require(config.functionsManifest)

assert.equal(manifest[slug[0]], slug[1])
assert.equal(manifest[fallback[0]], fallback[1])
assert.equal(fallback.route, `/:slug?`)
assert.ok(fallback.dest.includes(`fallback.js`))
})

test('outputLambdas - hashed in prod', async () => {
Expand All @@ -62,9 +57,9 @@ test('outputLambdas - hashed in prod', async () => {
const [slug] = outputLambdas([fixture.files.slug.path], config)
const hash = hashContent(fixture.files.slug.content)

assert.equal(slug[0], `/:slug`)
assert.ok(slug[1].includes(`slug-${hash}.js`))
assert.ok(fs.existsSync(slug[1]))
assert.equal(slug.route, `/:slug`)
assert.ok(slug.dest.includes(`slug-${hash}.js`))
assert.ok(fs.existsSync(slug.dest))
})

test('slugify', async () => {
Expand Down

0 comments on commit 3ab4afb

Please sign in to comment.