Upon deploying the application, the following environment variables must be set:
# Route53
ROUTE53_ZONE_NAME="<value_from_your_aws_account>"
ROUTE53_HOSTED_ZONE_ID="<value_from_your_aws_account>"
# EdgeDB
EDGEDB_INSTANCE_COUNT=1
EDGEDB_DOMAIN_NAME="edgedb.$ROUTE53_ZONE_NAME"
# Site
SITE_DOMAIN_NAME="site.$ROUTE53_ZONE_NAME"
# Api
API_DOMAIN_NAME="api.$ROUTE53_ZONE_NAME"
To develop the project locally, run npm run sst:start
and wait for the infrastructure deployment to finish. Don't cancel the command after it has finished deploying! While the command is running, SST provides you with a cloud native local development environment that gives you instantaneous feedback on edits made in your Lambda function code. Running npm run sst:console
will also provide you with a web based dashboard to debug and manage your infrastructure.
After running npm run sst:start
, you must also migrate the database by running npm run edgedb:link
and npm run edgedb:migrate
.
Working in a team of multiple developers? Follow this guide to prevent dev environments from conflicting while using a single AWS account.
Infrastructure is deployed to AWS with the help of SST and AWS CDK.
All IaC related code is located inside the sst-stacks
package. Custom CDK constructs are located inside the cdk-constructs
package and only referenced by the sst-stacks
package.
Before running database migrations, the EdgeDB CLI must be installed locally and linked to the remote EdgeDB instance deployed on AWS. To do this, run the following command:
npm run edgedb:link
Then, modify default.esdl
inside packages/edgedb/dbschema
to your liking and run the following command to create the migration for your changes:
npm run edgedb:create-migration
To apply the migration, run the following command:
npm run edgedb:migrate
Learn more about migrations from the official EdgeDB Guide.
To generate the EdgeDB query builder, run the following command:
npm run edgedb:generate-query-builder
The query builder will be written to the
edgedb
package. Learn more about the query builder from the following blog post.
You can import both query builder (e) and client like this:
import { e, client } from "@sst-app/edgedb";
// Run your queries against the client
e.insert(e.User, {
given_name: e.str(given_name),
family_name: e.str(family_name),
}).run(client);
This project uses tRPC for end-to-end type-safe APIs. Each service in the services
directory exposes its own tRPC router with its own queries and mutations.
Each app must have its own router inside the trpc-gateway
package, which represents the union of all service routers this app needs in order to fulfill its requirements.
Endpoints which mutate data on the server are called "mutations" in tRPC. To create a mutation, add it to its own file inside procedures/mutations
in the corresponding service.
Mutations typically look like this:
// <your_service>/src/procedures/mutations/demo.ts
import { procedure } from "@sst-app/trpc";
import { demoInputSchema } from "../../validators/demo";
export const demoMutation = procedure.input(demoInputSchema).mutation(async ({ input, ctx }) => {
// Do something, like writing to the database
// Access the typed input
console.log(input.firstName);
console.log(input.lastName);
// You can also return something which is sent to the client as JSON
return { success: true };
});
Don't forget to add the mutation to the router inside
router.ts
.
Mutations validate the input sent by the requesting client using a zod schema, which lays inside the validators
directory of the same service containing the mutation.
A validation schema which checks if the properties firstName
and lastName
are strings would look like this:
// <your_service>/src/validators/demo.ts
import { z } from "zod";
export const demoInputSchema = z.object({
firstName: z.string().min(1),
lastName: z.string().min(1),
});
export type DemoInput = z.infer<typeof demoInputSchema>;
Validators can also be exported in validators.ts
in the root of the service, which allows apps in the apps
directory to also import and use the same zod schemas to validate data client-side.
Endpoints which query data from the server are called "queries" in tRPC. To create a query, add it to its own file inside procedures/queries
in the corresponding service.
Queries typically look like this:
// <your_service>/src/procedures/queries/demo.ts
import { procedure } from "@sst-app/trpc";
import { demoInputSchema } from "../../validators/demo";
export const demoQuery = procedure.input(demoInputSchema).query(async ({ input, ctx }) => {
// Do something, like reading from the database
// Return your data
return { hello: "world" };
});
Don't forget to add the query to the router inside
router.ts
.
Validators work exactly the same way in queries as they do in mutations.
Contains user-facing apps (frontends).
Contains Lambda functions not accessible over the public network, like Lambda Triggers or Step Functions.
Contains packages used by apps, services and functions.
Contains Lambda microservices.
Deploy the infrastructure for development:
npm run sst:start
While developing Lambdas locally with
npm run sst:start
, apps must be run locally by runningnpm run dev
in the root directory.
Deploy the infrastructure:
npm run sst:deploy
Remove the infrastructure:
npm run sst:remove
Open the SST console:
npm run sst:console