Luca Demmel
07/02/2021, 10:44 AMthdxr
07/03/2021, 6:44 PMLuke Wyman
07/05/2021, 5:45 PMnpx create-serverless-stack@latest <microservice name>
in the parent folder for each microservice in the monorepo?
Or, one could also do the npx create-serverless-stack
once, and then put the microservices in each of their own directories under src
. And then, in lib
create one stack per microservice, each with the API, Lambda, DynamoDB table(s) and whatever other serverless pieces and deploy a stack per microservice.Adrián Mouly
07/05/2021, 9:03 PMLuke Wyman
07/06/2021, 12:01 AMtsconfig.json
should be referenced?:
Resolve error: ENOENT: no such file or directory, stat './tsconfig.json'
Ross Coundon
07/06/2021, 4:42 PMsst deploy
. I don't need to have any notifications attached to it. It's just going to be used to write data as a result of a call to an endpoint (also defined in SST)
Is there anything I need to other than this:
export default class SomeStack extends sst.Stack {
constructor(scope: <http://sst.App|sst.App>, id: string, props?: sst.StackProps) {
super(scope, id, props);
const statsCsvBucket = new Bucket(this, process.env.REBOOK_STATS_BUCKET);
}
}
thdxr
07/06/2021, 6:40 PMLuke Wyman
07/06/2021, 9:51 PMError: There is already a Construct with name 'SingersApi' in SingersStack [dev-karaoke-singers]
in the following sst/cdk Stack class:
import { RemovalPolicy } from '@aws-cdk/core';
import * as sst from '@serverless-stack/resources';
export default class SingersStack extends sst.Stack {
constructor(scope: <http://sst.App|sst.App>, id: string, props?: sst.StackProps) {
super(scope, id, props);
const singersTable = new sst.Table(this, "singers", {
fields: {
singer_id: sst.TableFieldType.STRING,
},
primaryIndex: { partitionKey: 'singer_id'},
dynamodbTable: {
removalPolicy: RemovalPolicy.DESTROY
}
});
const singersApi = new sst.Api(this, 'SingersApi', {
defaultFunctionProps: {
environment: {
singersTable: singersTable.dynamodbTable.tableName,
},
},
});
singersApi.addRoutes(this, {
'POST /karaoke/singers': 'src/services/singers/functions/KAR_SNG_create_singer.handler',
'GET /karaoke/singers/{singerId}': 'src/services/singers/functions/KAR_SNG_get_singer.handler',
'GET /karaoke/singers': 'src/services/singers/functions/KAR_SNG_get_all_singers.handler',
'PUT /karaoke/singers/{singerId}': 'src/services/singers/functions/KAR_SNG_update_singer.handler',
'DELETE /karaoke/singers/{singerId}': 'src/services/singers/functions/KAR_SNG_delete_singer.handler',
});
singersApi.attachPermissions([singersTable]);
this.addOutputs({
'SingersApi': {
value: singersApi.url,
exportName: scope.logicalPrefixedName('SingersApi'),
}
});
}
}
It seems having 'SingersApi' in both const singersApi = new sst.Api(this, 'SingersApi', {
and
this.addOutputs({
'SingersApi': {
value: singersApi.url,
exportName: scope.logicalPrefixedName('SingersApi'),
}
});
is a no-go. These seem like similar, yet different context meanings of the api parameter. The later is the Key and ExportName in CFN. But what is the same parameter in the sst.Api
constructor?Luke Wyman
07/06/2021, 11:58 PMLuke Wyman
07/07/2021, 5:51 PMDanny
07/08/2021, 1:07 PMMike McCall
07/08/2021, 5:04 PMMichael Orcutt
07/08/2021, 7:45 PMthdxr
07/09/2021, 12:39 AMMichael Orcutt
07/12/2021, 4:08 PMconst userPool = cognito.UserPool.fromUserPoolArn(
this,
// does this id matter?
'dev-user-pool',
process.env.AWS_USER_POOL_ARN,
)
const api = new sst.AppSyncApi(this, 'v2', {
graphqlApi: {
schema: 'src/schema/schema.graphql',
authorizationConfig: {
defaultAuthorization: {
authorizationType: appsync.AuthorizationType.USER_POOL,
userPoolConfig: {
userPool: userPool,
},
},
},
logConfig: {
excludeVerboseContent: false,
fieldLogLevel: appsync.FieldLogLevel.ALL,
},
},
resolvers: {
'Query projects': 'src/get-projects.main',
'Mutation createProject': 'src/create-project.main',
},
})
Luke Wyman
07/12/2021, 6:53 PMRyan
07/13/2021, 6:02 AMMike McCall
07/13/2021, 7:45 PMgeekmidas
07/14/2021, 8:24 PMthdxr
07/15/2021, 3:54 PMlib
with sst.jsonLuke Wyman
07/15/2021, 7:47 PMcustomAttributes
in for a Cognito UserPool? I've looked through all documentation, but I can't make heads or tails of how to implement ICustomAttribute
.
const auth = new sst.Auth(this, 'Auth', {
cognito: {
userPool: {
signInAliases: { email: true },
removalPolicy: RemovalPolicy.DESTROY,
customAttributes: {
FirstName: { ??? WHAT GOES HERE ??? }
}
},
triggers: {
preSignUp: 'src/triggers/preSignup.handler',
postConfirmation: 'src/triggers/postConfirmation.handler',
preAuthentication: 'src/triggers/preAuthentication.handler',
postAuthentication: 'src/triggers/postAuthentication.handler',
},
},
});
geekmidas
07/16/2021, 11:01 AMimport { App, Stack } from '@serverless-stack/resources';
import {
HttpApi,
} from '@aws-cdk/aws-apigatewayv2';
import { HttpAlbIntegration } from '@aws-cdk/aws-apigatewayv2-integrations';
import { Server } from './Server';
export class Api extends Stack {
constructor(app: App, props: Props) {
super(app, 'api');
const { server } = props;
const { fargate } = server;
const integration = new HttpAlbIntegration({
listener: fargate.listener,
});
new HttpApi(this, 'http-api', {
defaultIntegration: integration,
});
}
}
interface Props {
server: Server;
}
Michael Orcutt
07/16/2021, 7:12 PMgeekmidas
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.Luke Wyman
07/17/2021, 11:35 PMsst.Stack
class?geekmidas
07/19/2021, 8:20 AMErik Mikkelson
07/19/2021, 4:15 PMDavid Martin
07/19/2021, 7:40 PMgeekmidas
07/20/2021, 7:55 AMnew Api(this, 'Api', {
routes: {
'ANY /any': {
function: 'src/lambda/any.handler',
bundle: {
loader: {} // this does not seem to work
}
},
},
});
I get the desired functionality when I use
const func new Function(this, 'Function', {
handler: 'src/lambda/any.handler',
bundle: {
loader: {} // it works here
}
});
new Api(this, 'Api', {
routes: {
'ANY /any': {
function: func
},
},
});
I haven't had time to debug this issue.colin
07/20/2021, 6:44 PM// schema.graphql
# An object with an ID to support global identification.
interface Node {
id: ID!
}
// AppSync Schema
interface Node {
id: ID!
}
I know AWS doesnt support the normal graphql commenting spec 🙄 but I was under the impression we could use single line comments via the above method. See https://github.com/aws/aws-appsync-community/issues/38