-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #58 from lifeomic/proxyLambdaFunction
Use local lambda handler file
- Loading branch information
Showing
15 changed files
with
343 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { AlphaCliArguments, AlphaCliConfig } from '../types'; | ||
import { Argv } from 'yargs'; | ||
import { promises as fs } from 'fs'; | ||
import path from 'path'; | ||
import { parse } from 'dotenv'; | ||
import { load } from 'js-yaml'; | ||
|
||
const loadEnvFile = async (envFile: string) => { | ||
const ext = path.extname(envFile).toLowerCase(); | ||
const contents = await fs.readFile(envFile, 'utf-8'); | ||
let newEnv: Record<string, any> = {}; | ||
if (ext === '.env') { | ||
newEnv = parse(contents); | ||
} else if (ext === '.json') { | ||
newEnv = JSON.parse(contents); | ||
} else if (['.yaml', '.yml'].includes(ext)) { | ||
newEnv = load(contents) as Record<string, any>; | ||
} else { | ||
throw new Error(`Unable to load ${envFile}, unrecognized extension ${ext}`); | ||
} | ||
Object.assign(process.env, newEnv); | ||
}; | ||
|
||
export default (yargs: Argv) => { | ||
yargs | ||
.option('lambda-handler', { | ||
type: 'string', | ||
describe: 'A javascript/typescript lambda handler to send requests to', | ||
}) | ||
.option('env-file', { | ||
type: 'string', | ||
describe: 'File to load as environment variables when importing lambda', | ||
}); | ||
|
||
return async ( | ||
config: AlphaCliConfig, | ||
{ | ||
'lambda-handler': lambdaHandler, | ||
'env-file': envFile, | ||
}: AlphaCliArguments, | ||
) => { | ||
if (lambdaHandler) { | ||
if (envFile) { | ||
await loadEnvFile(envFile); | ||
} | ||
const exported = await import(lambdaHandler); | ||
config.lambda = exported.handler || exported.default.handler; | ||
} | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import path from 'path'; | ||
import { getPort, runCommand, spawnProxy } from './utils'; | ||
import { ulid } from 'ulid'; | ||
|
||
describe.each([ | ||
'exportApp', | ||
'exportHandler', | ||
])('can send requests to %s', (handlerFile) => { | ||
const param: string = ulid(); | ||
const filePath = path.join(__dirname, 'lambdaHandlers', `${handlerFile}.ts`); | ||
|
||
test('will send request to exported handler', async () => { | ||
const { stdout, stderr } = await runCommand('--lambda-handler', filePath, `/echo/${param}`); | ||
expect(stderr).toBeFalsy(); | ||
expect(stdout).toBe(param); | ||
}); | ||
|
||
test('will proxy requests to the exported handler', async () => { | ||
const proxyPort = await getPort(); | ||
const process = await spawnProxy('--proxy', '--proxy-port', proxyPort, '--lambda-handler', filePath); | ||
|
||
try { | ||
const { stdout, stderr } = await runCommand(`http://localhost:${proxyPort}/echo/${param}`); | ||
|
||
expect(stdout).toBe(param); | ||
expect(stderr).toBeFalsy(); | ||
} finally { | ||
process.kill(); | ||
} | ||
}); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Koa from 'koa'; | ||
import Router from '@koa/router'; | ||
import serverless from 'serverless-http'; | ||
|
||
const app = new Koa() as Koa & { handler: ReturnType<typeof serverless>; }; | ||
|
||
const router = new Router(); | ||
|
||
router.get('/echo/:param', (ctx) => { | ||
ctx.body = ctx.params.param; | ||
ctx.status = 200; | ||
}); | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
app.use(router.routes()); | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
app.use(router.allowedMethods()); | ||
|
||
app.handler = serverless(app); | ||
|
||
export default app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import Koa from 'koa'; | ||
import Router from '@koa/router'; | ||
import serverless from 'serverless-http'; | ||
|
||
const app = new Koa(); | ||
|
||
const router = new Router(); | ||
|
||
router.get('/echo/:param', (ctx) => { | ||
ctx.body = ctx.params.param; | ||
ctx.status = 200; | ||
}); | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
app.use(router.routes()); | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
app.use(router.allowedMethods()); | ||
|
||
export const handler = serverless(app); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import path from 'path'; | ||
import yargs from 'yargs'; | ||
import { ulid } from 'ulid'; | ||
import { dump } from 'js-yaml'; | ||
import { promises as fs } from 'fs'; | ||
|
||
import lambdaHandlerPlugin from '../../src/plugins/lambda-handler'; | ||
import { AlphaCliArguments, AlphaCliConfig } from '../../src/types'; | ||
|
||
const buildDir = path.join(__dirname, '..', 'build'); | ||
const lambdaHandler = path.join(__dirname, '..', 'lambdaHandlers', 'exportHandler.ts'); | ||
const pluginFunc = lambdaHandlerPlugin(yargs); | ||
|
||
beforeAll(async () => { | ||
await fs.mkdir(buildDir, { recursive: true }); | ||
}); | ||
|
||
test.each([ | ||
'exportHandler.ts', | ||
'exportApp.ts', | ||
])('%s will load the lambda-handler function', async (lambdaHandlerFile) => { | ||
const config: AlphaCliConfig = { | ||
responsePostProcessors: [], | ||
}; | ||
const cliArgs: AlphaCliArguments = { | ||
_: [''], | ||
'lambda-handler': path.join(__dirname, '..', 'lambdaHandlers', lambdaHandlerFile), | ||
}; | ||
await expect(pluginFunc(config, cliArgs)).resolves.toBeUndefined(); | ||
expect(config).toHaveProperty('lambda', expect.any(Function)); | ||
}); | ||
|
||
test('will throw exception on unknown extension', async () => { | ||
const ext = `.${ulid()}`; | ||
const envFile = path.join(buildDir, `${ulid()}${ext.toUpperCase()}`); | ||
await fs.writeFile(envFile, '', 'utf-8'); | ||
|
||
const config: AlphaCliConfig = { | ||
responsePostProcessors: [], | ||
}; | ||
const cliArgs: AlphaCliArguments = { | ||
_: [''], | ||
'lambda-handler': lambdaHandler, | ||
'env-file': envFile, | ||
}; | ||
try { | ||
await expect(pluginFunc(config, cliArgs)).rejects.toThrowError(`Unable to load ${envFile}, unrecognized extension ${ext.toLowerCase()}`); | ||
} finally { | ||
await fs.rm(envFile, { force: true }); | ||
} | ||
}); | ||
|
||
describe.each([ | ||
'json', | ||
'yaml', | ||
'yml', | ||
'env', | ||
])('will load %s into the process.env', (ext) => { | ||
const envFile = path.join(buildDir, `${ulid()}.${ext}`); | ||
const envVars = { | ||
[ulid()]: ulid(), | ||
}; | ||
beforeAll(async () => { | ||
let envString = ''; | ||
if (ext === 'json') { | ||
envString = JSON.stringify(envVars); | ||
} else if (ext === 'env') { | ||
envString = Object.entries(envVars).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join('\n'); | ||
} else if (['yaml', 'yml'].includes(ext)) { | ||
envString = dump(envVars); | ||
} | ||
|
||
await fs.writeFile(envFile, envString, 'utf-8'); | ||
}); | ||
afterAll(async () => { | ||
await fs.rm(envFile, { force: true }); | ||
}); | ||
|
||
test('will load the env file', async () => { | ||
const config: AlphaCliConfig = { | ||
responsePostProcessors: [], | ||
}; | ||
const cliArgs: AlphaCliArguments = { | ||
_: [''], | ||
'lambda-handler': lambdaHandler, | ||
'env-file': envFile, | ||
}; | ||
await expect(pluginFunc(config, cliArgs)).resolves.toBeUndefined(); | ||
expect(process.env).toStrictEqual(expect.objectContaining(envVars)); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.