geekmidas
07/16/2021, 7:40 PMimport fs from 'fs';
import path from 'path';
import { Stack, Function, FunctionProps } from '@serverless-stack/resources';
import { getPathConstruct } from './formatting';
const INITIAL_RECORDS: LambdaRecords = {};
/**
* Creates functions for all files in the provided directory
*
* @param stack - The stack in which the functions belong to
* @param directory - The directory where the functions should be created from
* @param props - Common handler props that you need to pass down to your functions
*
* @returns A record of the lambda functions with the keys as the PascalCase version of the filename
*/
export function getPathFunctions(
stack: Stack,
directory: string,
props: LambdaProps = {},
) {
const { stage } = stack;
const root = process.cwd();
const dir = directory.replace(`${root}/`, '');
const functions = fs.readdirSync(directory);
return functions.reduce((memo, filename) => {
const fullPath = path.resolve(directory, filename);
const stats = fs.statSync(fullPath);
if (stats.isDirectory()) {
return memo;
}
const [name] = filename.split('.');
const constructName = getPathConstruct(filename);
const functionName = `${stage}-${name}`;
const id = `${constructName}Lambda`;
const handler = `${dir}/${name}.handler`;
const lambdaFunction = new Function(stack, id, {
handler,
functionName,
...props,
});
return {
...memo,
[constructName]: lambdaFunction,
};
}, INITIAL_RECORDS);
}
type LambdaProps = Omit<Omit<FunctionProps, 'handler'>, 'functionName'>
export type LambdaRecords = Record<string, Function>;
Do you guys think this would be a valuable thing to add? We could add a static method on the Function class like Function.fromDirectory(...)
obviously we would have to make the functionality more generic.Frank
app.setDefaultFunctionProps({
runtime: ...,
environment: { ... },
});
And you can create a function by just supplying the handler path, ie:
routes: {
"Get /users": "src/list_users.main",
"POST /users": "src/create_user.main",
}
Frank
Nick Laffey
07/16/2021, 9:27 PMNick Laffey
07/16/2021, 9:27 PMFrank
geekmidas
07/16/2021, 9:34 PMconst LAMBDA_ROOT = path.resolve(ROOT, 'src/api');
... // My Api Stack had this
const api = getPathFunctions(this, LAMBDA_ROOT, {
environment,
timeout: Duration.seconds(29),
bundle: {
nodeModules: ['knex'],
},
});
const { CreateUser, GetAuthFlow, Graphql } = api;
const domainName = `${prefix}<http://api.crownrescue.com|api.crownrescue.com>`;
this.handler = Graphql;
new SSTApi(this, 'Api', {
routes: {
'ANY /graphql': {
authorizationType: ApiAuthorizationType.JWT,
function: Graphql,
authorizer: new HttpUserPoolAuthorizer({
authorizerName: 'UserPoolAuthorizer',
userPool,
userPoolClient,
userPoolRegion: region,
}),
},
'POST /auth': {
function: GetAuthFlow,
},
'POST /create-user': {
function: CreateUser,
},
},
customDomain: {
domainName,
hostedZone: '...',
},
});
...
and my Cognito Stack has this
const TRIGGERS_ROOT = path.resolve(ROOT, 'src/triggers');
const triggers = getPathFunctions(this, TRIGGERS_ROOT, {
timeout: Duration.seconds(29),
});
const {
PreSignUp,
CreateAuthChallenge,
DefineAuthChallenge,
VerifyAuthChallengeResponse,
} = triggers;
geekmidas
07/16/2021, 9:35 PMNick Laffey
07/16/2021, 9:41 PMNick Laffey
07/16/2021, 9:43 PMNick Laffey
07/16/2021, 9:44 PMgeekmidas
07/16/2021, 9:45 PMNick Laffey
07/16/2021, 9:48 PMgeekmidas
07/16/2021, 9:51 PMFrank
Nick Laffey
07/16/2021, 9:56 PMFrank