Skip to content

microeinhundert/sst-edgedb-trpc-microservices

Repository files navigation

SST Microservices Architecture

Infrastructure

Prerequisites

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"

Developing locally

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.

Modifying infrastructure

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.

Working with EdgeDB

Migrations

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.

Query Builder

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.

Usage

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);

Creating endpoints

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.

Creating a mutation (POST Endpoint)

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.

Creating a query (GET Endpoint)

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.

Directories

/apps

Contains user-facing apps (frontends).

/functions

Contains Lambda functions not accessible over the public network, like Lambda Triggers or Step Functions.

/packages

Contains packages used by apps, services and functions.

/services

Contains Lambda microservices.

Commands

Deploy the infrastructure for development:

npm run sst:start

While developing Lambdas locally with npm run sst:start, apps must be run locally by running npm 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

About

Microservices deployed to AWS. Built with SST, tRPC and EdgeDB.

Resources

Stars

Watchers

Forks