Rudi
05/23/2022, 8:09 PMexport default function main(app) {
app.setDefaultFunctionProps({
runtime: "nodejs16.x",
srcPath: "backend",
bundle: {
format: "esm",
},
})
const storageStack = new StorageStack(app, "storage")
app.stack(storageStack).stack(ApiStack)
}
but now get:
Stacks: Building changes...
Stacks: Synthesizing changes...
TypeError: fn is not a function
at stack (/home/rudi/projects/notes/node_modules/@serverless-stack/resources/src/FunctionalStack.ts:23:19)
at App.stack (/home/rudi/projects/notes/node_modules/@serverless-stack/resources/src/App.ts:389:17)
at Object.main (/home/rudi/projects/notes/stacks/index.js:19:7)
at Object.<anonymous> (/home/rudi/projects/notes/.build/run.js:94:16)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at internal/main/run_main_module.js:17:47
thdxr
05/23/2022, 8:10 PMnew StorageStack
if you are using functional stacksthdxr
05/23/2022, 8:10 PMthdxr
05/23/2022, 8:10 PMapp.stack(storageStack).stack(ApiStack)
thdxr
05/23/2022, 8:11 PMRudi
05/23/2022, 8:12 PMimport * as sst from "@serverless-stack/resources"
export default class StorageStack extends sst.Stack {
// Public reference to the bucket
bucket
// Public reference to the table
table
constructor(scope, id, props) {
super(scope, id, props)
// Create the DynamoDB table
this.table = new sst.Table(this, "Notes", {
fields: {
userId: sst.TableFieldType.STRING,
noteId: sst.TableFieldType.STRING,
},
primaryIndex: { partitionKey: "userId", sortKey: "noteId" },
})
// Create an S3 bucket
this.bucket = new sst.Bucket(this, "Uploads")
}
}
Rudi
05/23/2022, 8:12 PMthdxr
05/23/2022, 8:12 PMapp.stack(...)
lineRudi
05/23/2022, 8:15 PMimport StorageStack from "./StorageStack"
import { ApiStack } from "./ApiStack"
// export default function main(app) {
// new StorageStack(app, "storage")
// }
export default function main(app) {
app.setDefaultFunctionProps({
runtime: "nodejs16.x",
srcPath: "backend",
bundle: {
format: "esm",
},
})
new StorageStack(app, "storage")
}
thdxr
05/23/2022, 8:15 PMnew ApiStack(...)
Rudi
05/23/2022, 8:16 PMthdxr
05/23/2022, 8:16 PMRudi
05/23/2022, 8:16 PMimport StorageStack from "./StorageStack"
import { ApiStack } from "./ApiStack"
// export default function main(app) {
// new StorageStack(app, "storage")
// }
export default function main(app) {
app.setDefaultFunctionProps({
runtime: "nodejs16.x",
srcPath: "backend",
bundle: {
format: "esm",
},
})
new StorageStack(app, "storage")
new ApiStack(app, "api")
}
thdxr
05/23/2022, 8:16 PMRudi
05/23/2022, 8:17 PMRudi
05/23/2022, 8:17 PMRudi
05/23/2022, 8:18 PMRudi
05/23/2022, 8:20 PMimport { Api, use } from "@serverless-stack/resources"
import StorageStack from "./StorageStack"
export function ApiStack({ stack, app }) {
const { table } = use(StorageStack)
with:
Stacks: Building changes...
Stacks: Synthesizing changes...
Error: No app is set
at use (/home/rudi/projects/notes/node_modules/@serverless-stack/resources/src/FunctionalStack.ts:43:26)
at new ApiStack (/home/rudi/projects/notes/stacks/ApiStack.js:5:21)
at Object.main (/home/rudi/projects/notes/stacks/index.js:18:3)
at Object.<anonymous> (/home/rudi/projects/notes/.build/run.js:94:16)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at internal/main/run_main_module.js:17:47
so I'll need to alter that bit too...Rudi
05/23/2022, 8:20 PMKlaus
05/23/2022, 9:07 PMexport function ApiStack({ stack, app }) {
var api = new Api(stack, 'api', {
routes: {
'GET /': 'functions/lambda.handler'
}
});
stack.addOutputs({ apiUrl: api.url });
return api;
}
Rudi
05/23/2022, 10:58 PMKlaus
05/24/2022, 1:21 AMimport {
Table,
Function,
Api,
use,
StackContext
} from '@serverless-stack/resources';
export function FuncStack({ stack, app }: StackContext) {
const fn = new Function(stack, `myFunc`, {
handler: 'lambda.handler',
srcPath: 'backend/functions'
});
return fn;
}
export function TableStack({ stack, app }: StackContext) {
var fn = use(FuncStack);
var tbl = new Table(stack, 'Notes', {
fields: {
noteId: 'string'
},
stream: true,
primaryIndex: { partitionKey: 'noteId' },
consumers: {
consumer1: fn
}
});
fn.addEnvironment('Table', tbl.tableArn);
return tbl;
}
export function ApiStack({ stack, app }: StackContext) {
var fn = use(FuncStack);
var api = new Api(stack, 'api', {
routes: {
'GET /': fn
}
});
stack.addOutputs({ apiUrl: api.url });
return api;
}
index.ts
import { FuncStack, TableStack, ApiStack } from './MyStacks';
import * as sst from '@serverless-stack/resources';
export default function (app: <http://sst.App|sst.App>) {
app.setDefaultFunctionProps({
runtime: 'python3.8',
srcPath: 'backend',
memorySize: 512
// environment: { ...env_vars }
});
app.stack(FuncStack).stack(TableStack).stack(ApiStack);
}
Rudi
05/24/2022, 1:54 AMRudi
05/24/2022, 6:32 PMimport * as sst from "@serverless-stack/resources"
/**
export default class StorageStack extends sst.Stack {
// Public reference to the bucket
bucket
// Public reference to the table
table
constructor(scope, id, props) {
super(scope, id, props)
// Create the DynamoDB table
this.table = new sst.Table(this, "Notes", {
fields: {
userId: sst.TableFieldType.STRING,
noteId: sst.TableFieldType.STRING,
},
primaryIndex: { partitionKey: "userId", sortKey: "noteId" },
})
// Create an S3 bucket
this.bucket = new sst.Bucket(this, "Uploads")
}
}
*/
export function StorageStack(ctx) {
// Create the DynamoDB table
const table = new sst.Table(ctx.stack, "Notes", {
fields: {
userId: sst.TableFieldType.STRING,
noteId: sst.TableFieldType.STRING,
},
primaryIndex: { partitionKey: "userId", sortKey: "noteId" },
})
// Create an S3 bucket
const bucket = new sst.Bucket(ctx.stack, "Uploads")
return { table, bucket }
}
But I get an unset env TABLE_NAME error:
23a8a76b-5a9f-4701-82ca-f1a69d7debdc RESPONSE {"statusCode":500,"body":"{\"error\":\"Missing required key 'TableName' in params\"}"}
I've tried debugging but am still stuck .. here you can see me trying some things within the ApiStack
import { StorageStack } from "./StorageStack"
import { Api, use } from "@serverless-stack/resources"
export function ApiStack({ stack, app }) {
const { table } = use(StorageStack)
console.log(table)
console.log("tn", table.tableName)
// Create the API
const api = new Api(stack, "Api", {
defaults: {
function: {
permissions: [table],
environment: {
// TABLE_NAME: table.tableName,
TABLE_NAME: "Notes",
},
},
},
routes: {
"POST /notes": "functions/create.main",
},
})
// Show the API endpoint in the output
stack.addOutputs({
ApiEndpoint: api.url,
})
// Return the API resource
return {
api,
}
}
Not sure where I'm going wrong?Rudi
05/24/2022, 6:32 PMtableArn: '${Token[TOKEN.204]}',
tableName: '${Token[TOKEN.206]}',
tableStreamArn: undefined,
scalingRole: <ref *3> Import {
node: [Node],
stack: [EmptyStack],
env: [Object],
_physicalName: undefined,
_allowCrossEnvironment: false,
physicalName: '${Token[TOKEN.207]}',
grantPrincipal: [Circular *3],
principalAccount: '771316991410',
assumeRoleAction: 'sts:AssumeRole',
policyFragment: [PrincipalPolicyFragment],
roleArn: 'arn:${Token[AWS.Partition.10]}:iam::771316991410:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable',
roleName: 'AWSServiceRoleForApplicationAutoScaling_DynamoDBTable',
attachedPolicies: [AttachedPolicies],
[Symbol(@aws-cdk/core.DependableTrait)]: [Object]
},
tablePartitionKey: { name: 'userId', type: 'S' },
tableSortKey: { name: 'noteId', type: 'S' },
[Symbol(@aws-cdk/core.DependableTrait)]: { dependencyRoots: [Array] }
},
[Symbol(@aws-cdk/core.DependableTrait)]: { dependencyRoots: [ [Circular *1] ] }
}
tn ${Token[TOKEN.206]}
Stacks: No changes to deploy.
23a8a76b-5a9f-4701-82ca-f1a69d7debdc REQUEST rudijs-notes-ApiStack-ApiLambdaPOSTnotes3B067E1B-XatYmYjQpgBB [functions/create.main] invoked by API POST /notes
TABLE_NAME undefined
23a8a76b-5a9f-4701-82ca-f1a69d7debdc RESPONSE {"statusCode":500,"body":"{\"error\":\"Missing required key 'TableName' in params\"}"}
Rudi
05/24/2022, 6:36 PMimport * as uuid from "uuid"
import AWS from "aws-sdk"
const dynamoDb = new AWS.DynamoDB.DocumentClient()
export async function main(event) {
console.log("TABLE_NAME", process.env.TABLE_NAME)
// Request body is passed in as a JSON encoded string in 'event.body'
const data = JSON.parse(event.body)
const params = {
TableName: process.env.TABLE_NAME,
Item: {
// The attributes of the item to be created
userId: "123", // The id of the author
noteId: uuid.v1(), // A unique uuid
content: data.content, // Parsed from request body
attachment: data.attachment, // Parsed from request body
createdAt: Date.now(), // Current Unix timestamp
},
}
try {
await dynamoDb.put(params).promise()
return {
statusCode: 200,
body: JSON.stringify(params.Item),
}
} catch (e) {
return {
statusCode: 500,
body: JSON.stringify({ error: e.message }),
}
}
}
Klaus
05/24/2022, 7:24 PMconst api = new Api(stack, "Api", {
defaults: {
function: {
permissions: [table],
environment: {
// TABLE_NAME: table.tableName,
TABLE_NAME: "Notes",
},
},
},
by
const api = new Api(stack, "Api", {
defaults: {
function: {
permissions: [table, bucket], // <-- also grant bucket permissions
environment: {
TABLE_NAME: table.tableName, // <-- set the table name correctly
// TABLE_NAME: "Notes",
},
},
},
the console log suggest the table reference is working, but it doesn't seem to be set in the environment correctlyRudi
05/24/2022, 7:30 PMRudi
05/24/2022, 7:30 PMKlaus
05/24/2022, 7:31 PMRudi
05/24/2022, 7:32 PMKlaus
05/24/2022, 7:32 PMRudi
05/24/2022, 7:33 PMKlaus
05/24/2022, 7:33 PMRudi
05/24/2022, 7:34 PMthdxr
05/24/2022, 7:42 PMthdxr
05/24/2022, 7:43 PMif (!["prod", "stage"].includes(app.stage))
app.setDefaultRemovalPolicy("destroy")
fyi for auto removalKlaus
05/24/2022, 7:48 PMserverless
it's hard getting food to be served by someone else😜Rudi
05/24/2022, 8:02 PMRudi
05/24/2022, 8:48 PMexport function StorageStack(ctx) {
// Create the DynamoDB table
const table = new sst.Table(ctx.stack, "Notes", {
fields: {
userId: sst.TableFieldType.STRING,
noteId: sst.TableFieldType.STRING,
},
primaryIndex: { partitionKey: "userId", sortKey: "noteId" },
})
// Create an S3 bucket
const bucket = new sst.Bucket(ctx.stack, "Uploads")
return { table, bucket }
}
..
export function ApiStack({ stack, app }) {
const { table } = use(StorageStack)
// Create the API
const api = new Api(stack, "Api", {
defaults: {
function: {
permissions: [table],
environment: {
TABLE_NAME: table.tableName,
},
},
},
routes: {
"POST /notes": "functions/create.main",
},
})
// Show the API endpoint in the output
stack.addOutputs({
ApiEndpoint: api.url,
})
// Return the API resource
return {
api,
}
}
..
import { StorageStack } from "./StorageStack"
import { ApiStack } from "./ApiStack"
// export default function main(app) {
// new StorageStack(app, "storage")
// }
export default function main(app) {
app.setDefaultFunctionProps({
runtime: "nodejs14.x",
srcPath: "src/backend",
bundle: {
format: "esm",
},
})
if (!["prod", "stage"].includes(app.stage)) app.setDefaultRemovalPolicy("destroy")
app.stack(StorageStack).stack(ApiStack)
}
output:
==========================
Starting Live Lambda Dev
==========================
SST Console: <https://console.serverless-stack.com/notes/rudijs/local>
Debug session started. Listening for requests...
82f2897d-06fd-4b64-9727-f2048beac283 REQUEST rudijs-notes-ApiStack-ApiLambdaPOSTnotes3B067E1B-YqzFbYWPVrdr [functions/create.main] invoked by API POST /notes
TABLE_NAME undefined
82f2897d-06fd-4b64-9727-f2048beac283 RESPONSE {"statusCode":500,"body":"{\"error\":\"Missing required key 'TableName' in params\"}"}
It deploys OK, but env is not being set.Rudi
05/24/2022, 8:49 PMthdxr
05/24/2022, 8:50 PMRudi
05/24/2022, 8:52 PMnpx sst --version main
SST: 0.69.7
CDK: 2.15.0
Rudi
05/24/2022, 8:52 PMRudi
05/24/2022, 8:53 PMKlaus
05/24/2022, 8:54 PMthdxr
05/24/2022, 8:54 PMthdxr
05/24/2022, 8:54 PMthdxr
05/24/2022, 8:54 PMuserId: "string",
noteId: "string",
thdxr
05/24/2022, 8:55 PMKlaus
05/24/2022, 8:55 PMnpm init sst
should create a repo with latest SSTRudi
05/24/2022, 8:56 PMthdxr
05/24/2022, 8:56 PMthdxr
05/24/2022, 8:56 PMKlaus
05/24/2022, 8:57 PMnpx sst update
Klaus
05/24/2022, 8:57 PMRudi
05/24/2022, 9:03 PMnpx sst update
Updating @serverless-stack/cli to latest
Updating @serverless-stack/resources to latest
Updating aws-cdk-lib@2.24.0
SST: 1.2.3
CDK: 2.24.0
Rudi
05/24/2022, 9:06 PMTypeError: Cannot read property 'STRING' of undefined
updating to "string" and re-deploying ..Rudi
05/24/2022, 9:07 PM===============
Deploying app
===============
ReferenceError: require is not defined
at App.applyRemovalPolicy (file:///home/rudi/projects/notes/node_modules/@serverless-stack/resources/dist/App.js:245:42)
at file:///home/rudi/projects/notes/node_modules/@serverless-stack/resources/dist/App.js:276:58
at Array.forEach (<anonymous>)
thdxr
05/24/2022, 9:08 PMthdxr
05/24/2022, 9:08 PMRudi
05/24/2022, 9:09 PMRudi
05/24/2022, 9:15 PM===============
Deploying app
===============
/home/rudi/projects/notes/node_modules/aws-cdk-lib/aws-autoscaling/lib/auto-scaling-group.d.ts (672,15): Cannot find name 'Set'. Do you need to change your target library? Try changing the 'lib' compiler o
ption to 'es2015' or later.
670. */
671. _metrics: Set<GroupMetric>;
672. constructor(...metrics: GroupMetric[]);
Deploying stacks
Rudi
05/24/2022, 9:15 PMRudi
05/24/2022, 9:16 PMRudi
05/24/2022, 9:17 PMRudi
05/24/2022, 9:18 PM// if (!["prod", "stage"].includes(app.stage)) app.setDefaultRemovalPolicy("destroy")
but looking forward to when that's good to go againRudi
05/24/2022, 9:19 PMKlaus
05/24/2022, 9:31 PMsst start
it worked fine.Klaus
05/24/2022, 9:31 PMthdxr
05/24/2022, 9:31 PM