├── .nvmrc ├── .npmrc ├── packages ├── trpc │ ├── .gitignore │ ├── .prettierignore │ ├── .eslintignore │ ├── README.md │ ├── tsconfig.json │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── init.ts │ │ │ └── createContext.ts │ └── package.json ├── common │ ├── .gitignore │ ├── .eslintignore │ ├── .prettierignore │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── validation.ts │ │ │ └── constants.ts │ ├── README.md │ ├── tsconfig.json │ └── package.json ├── edgedb │ ├── src │ │ ├── lib │ │ │ └── .gitkeep │ │ └── index.ts │ ├── .eslintignore │ ├── .gitignore │ ├── .prettierignore │ ├── edgedb.toml │ ├── README.md │ ├── scripts │ │ ├── generate-query-builder.sh │ │ └── link.sh │ ├── tsconfig.json │ ├── dbschema │ │ ├── default.esdl │ │ └── migrations │ │ │ ├── 00001.edgeql │ │ │ └── 00002.edgeql │ └── package.json ├── tsconfig │ ├── .gitignore │ ├── .prettierignore │ ├── src │ │ └── index.js │ ├── README.md │ ├── presets │ │ ├── service-preset.json │ │ ├── package-preset.json │ │ ├── vite-app-preset.json │ │ ├── remix-app-preset.json │ │ └── base-preset.json │ └── package.json ├── types │ ├── .gitignore │ ├── .eslintignore │ ├── .prettierignore │ ├── src │ │ └── index.ts │ ├── README.md │ ├── tsconfig.json │ └── package.json ├── auth-utils │ ├── .gitignore │ ├── .eslintignore │ ├── .prettierignore │ ├── README.md │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ └── createAuthenticationFlow.ts │ ├── tsconfig.json │ └── package.json ├── cdk-constructs │ ├── .gitignore │ ├── .prettierignore │ ├── .eslintignore │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ └── EdgeDB.ts │ ├── README.md │ ├── tsconfig.json │ └── package.json ├── lambda-utils │ ├── .gitignore │ ├── .prettierignore │ ├── .eslintignore │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ └── getSecretValue.ts │ ├── README.md │ ├── tsconfig.json │ └── package.json ├── sst-stacks │ ├── .gitignore │ ├── .eslintignore │ ├── .prettierignore │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── utils │ │ │ ├── crypto.ts │ │ │ ├── general.ts │ │ │ ├── auth.ts │ │ │ └── api.ts │ │ │ ├── Config.ts │ │ │ ├── env │ │ │ ├── formatErrors.ts │ │ │ ├── index.ts │ │ │ └── schema.ts │ │ │ ├── App.ts │ │ │ ├── Api.ts │ │ │ ├── Services.ts │ │ │ ├── Apps.ts │ │ │ ├── Persistence.ts │ │ │ └── Auth.ts │ ├── README.md │ ├── tsconfig.json │ └── package.json ├── trpc-gateway │ ├── .gitignore │ ├── .prettierignore │ ├── .eslintignore │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── routers │ │ │ └── site.ts │ │ │ ├── links │ │ │ └── site.ts │ │ │ └── createGatewayLink.ts │ ├── README.md │ ├── tsconfig.json │ └── package.json ├── eslint-config-custom │ ├── .gitignore │ ├── .prettierignore │ ├── README.md │ ├── package.json │ └── src │ │ └── index.js └── README.md ├── services ├── auth │ ├── .gitignore │ ├── .eslintignore │ ├── .prettierignore │ ├── index.ts │ ├── README.md │ ├── tsconfig.json │ ├── handlers.ts │ ├── src │ │ ├── procedures │ │ │ ├── mutations │ │ │ │ ├── credentials.ts │ │ │ │ └── credentials │ │ │ │ │ ├── issue.ts │ │ │ │ │ └── refresh.ts │ │ │ └── queries │ │ │ │ └── userInfo.ts │ │ ├── router.ts │ │ ├── validators │ │ │ ├── userInfo.ts │ │ │ ├── refreshCredentials.ts │ │ │ └── issueCredentials.ts │ │ └── utils │ │ │ └── fetchCognito.ts │ ├── validators.ts │ └── package.json ├── demo │ ├── .gitignore │ ├── .eslintignore │ ├── .prettierignore │ ├── src │ │ ├── validators │ │ │ └── .gitkeep │ │ ├── procedures │ │ │ ├── mutations │ │ │ │ └── .gitkeep │ │ │ └── queries │ │ │ │ └── helloWorld.ts │ │ └── router.ts │ ├── index.ts │ ├── README.md │ ├── validators.ts │ ├── tsconfig.json │ ├── handlers.ts │ └── package.json └── README.md ├── .eslintignore ├── functions ├── pre-sign-up-trigger │ ├── src │ │ └── .gitkeep │ ├── .gitignore │ ├── .eslintignore │ ├── .prettierignore │ ├── index.ts │ ├── README.md │ ├── tsconfig.json │ ├── handlers.ts │ └── package.json └── README.md ├── .prettierignore ├── apps ├── site │ ├── .eslintignore │ ├── .prettierignore │ ├── .gitignore │ ├── app │ │ ├── styles │ │ │ └── app.css │ │ ├── sst-env.d.ts │ │ ├── routes │ │ │ ├── auth │ │ │ │ ├── logout.tsx │ │ │ │ └── callback.tsx │ │ │ ├── index.tsx │ │ │ └── private.tsx │ │ ├── server │ │ │ ├── session.server.ts │ │ │ ├── cookies.server.ts │ │ │ ├── env.server.ts │ │ │ └── auth.server.ts │ │ ├── utils │ │ │ ├── env.ts │ │ │ └── trpc.ts │ │ ├── entry.client.tsx │ │ ├── entry.server.tsx │ │ └── root.tsx │ ├── public │ │ └── favicon.ico │ ├── remix.config.js │ ├── tailwind.config.js │ ├── README.md │ ├── tsconfig.json │ └── package.json └── README.md ├── .husky └── pre-commit ├── assets └── infrastructure.png ├── sst.json ├── .ncurc.json ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── .env.example ├── .editorconfig ├── turbo.json ├── .gitignore ├── package.json └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | loglevel=error -------------------------------------------------------------------------------- /packages/trpc/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /services/auth/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /services/demo/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/common/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/edgedb/src/lib/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/trpc/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/tsconfig/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/types/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /services/auth/.eslintignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /services/auth/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /services/demo/.eslintignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /services/demo/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/auth-utils/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/cdk-constructs/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/common/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /packages/common/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/lambda-utils/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/sst-stacks/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/trpc-gateway/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/trpc/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /packages/tsconfig/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/types/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /packages/types/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /services/demo/src/validators/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .build 2 | .sst 3 | dist 4 | -------------------------------------------------------------------------------- /functions/pre-sign-up-trigger/src/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/auth-utils/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /packages/auth-utils/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/cdk-constructs/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/lambda-utils/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/sst-stacks/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /packages/sst-stacks/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/trpc-gateway/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/tsconfig/src/index.js: -------------------------------------------------------------------------------- 1 | // Noop 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .build 2 | .sst 3 | dist 4 | -------------------------------------------------------------------------------- /functions/pre-sign-up-trigger/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/cdk-constructs/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /packages/eslint-config-custom/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/lambda-utils/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /packages/trpc-gateway/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /services/demo/src/procedures/mutations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /functions/pre-sign-up-trigger/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /functions/pre-sign-up-trigger/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /functions/pre-sign-up-trigger/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/eslint-config-custom/.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /apps/site/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | build 3 | public/build -------------------------------------------------------------------------------- /packages/edgedb/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | src/lib/queryBuilder -------------------------------------------------------------------------------- /packages/edgedb/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | src/lib/queryBuilder -------------------------------------------------------------------------------- /packages/edgedb/.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | src/lib/queryBuilder -------------------------------------------------------------------------------- /packages/edgedb/edgedb.toml: -------------------------------------------------------------------------------- 1 | [edgedb] 2 | server-version = "*" 3 | -------------------------------------------------------------------------------- /services/auth/index.ts: -------------------------------------------------------------------------------- 1 | export { router } from "./src/router"; 2 | -------------------------------------------------------------------------------- /services/demo/index.ts: -------------------------------------------------------------------------------- 1 | export { router } from "./src/router"; 2 | -------------------------------------------------------------------------------- /apps/README.md: -------------------------------------------------------------------------------- 1 | # Apps 2 | 3 | Contains user-facing apps (frontends). 4 | -------------------------------------------------------------------------------- /services/README.md: -------------------------------------------------------------------------------- 1 | # Services 2 | 3 | Contains Lambda microservices. 4 | -------------------------------------------------------------------------------- /packages/types/src/index.ts: -------------------------------------------------------------------------------- 1 | export type MaybePromise = Promise | T; 2 | -------------------------------------------------------------------------------- /packages/cdk-constructs/src/index.ts: -------------------------------------------------------------------------------- 1 | export { EdgeDB } from "./lib/EdgeDB"; 2 | -------------------------------------------------------------------------------- /services/auth/README.md: -------------------------------------------------------------------------------- 1 | # Auth Service 2 | 3 | Service for authentication. 4 | -------------------------------------------------------------------------------- /apps/site/.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | build 3 | public/build 4 | app/styles/app-compiled.css -------------------------------------------------------------------------------- /services/demo/README.md: -------------------------------------------------------------------------------- 1 | # Demo Service 2 | 3 | Service for demonstration purposes. 4 | -------------------------------------------------------------------------------- /packages/lambda-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export { getSecretValue } from "./lib/getSecretValue"; 2 | -------------------------------------------------------------------------------- /packages/trpc/README.md: -------------------------------------------------------------------------------- 1 | # tRPC 2 | 3 | This package contains the tRPC server client. 4 | -------------------------------------------------------------------------------- /packages/types/README.md: -------------------------------------------------------------------------------- 1 | # Types 2 | 3 | This package contains shared TypeScript types. 4 | -------------------------------------------------------------------------------- /apps/site/.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | dist 3 | build 4 | public/build 5 | app/styles/app-compiled.css -------------------------------------------------------------------------------- /packages/README.md: -------------------------------------------------------------------------------- 1 | # Packages 2 | 3 | Contains packages used by apps, services and functions. 4 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/index.ts: -------------------------------------------------------------------------------- 1 | import App from "./lib/App"; 2 | 3 | export default App; 4 | -------------------------------------------------------------------------------- /apps/site/app/styles/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /packages/common/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./lib/constants"; 2 | export * from "./lib/validation"; 3 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npm run pre-commit 5 | -------------------------------------------------------------------------------- /packages/auth-utils/README.md: -------------------------------------------------------------------------------- 1 | # Auth Utils 2 | 3 | This package contains utilities for authentication. 4 | -------------------------------------------------------------------------------- /packages/auth-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createAuthenticationFlow } from "./lib/createAuthenticationFlow"; 2 | -------------------------------------------------------------------------------- /packages/lambda-utils/README.md: -------------------------------------------------------------------------------- 1 | # Lambda Utils 2 | 3 | This package contains utilities used across Lambda functions. 4 | -------------------------------------------------------------------------------- /apps/site/app/sst-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /assets/infrastructure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microeinhundert/sst-edgedb-trpc-microservices/HEAD/assets/infrastructure.png -------------------------------------------------------------------------------- /packages/edgedb/README.md: -------------------------------------------------------------------------------- 1 | # EdgeDB 2 | 3 | This package contains the EdgeDB schema as well as the auto-generated query builder. 4 | -------------------------------------------------------------------------------- /services/demo/validators.ts: -------------------------------------------------------------------------------- 1 | // This package entrypoint allows you to export your zod schemas for use in apps 2 | 3 | export {}; 4 | -------------------------------------------------------------------------------- /sst.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-sst-app", 3 | "region": "eu-central-1", 4 | "main": "packages/sst-stacks/src/index.ts" 5 | } 6 | -------------------------------------------------------------------------------- /.ncurc.json: -------------------------------------------------------------------------------- 1 | { 2 | "upgrade": true, 3 | "deep": true, 4 | "reject": ["@serverless-stack/*", "aws-cdk-lib", "@types/node"] 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint", "magicstack.edgedb"] 3 | } 4 | -------------------------------------------------------------------------------- /apps/site/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microeinhundert/sst-edgedb-trpc-microservices/HEAD/apps/site/public/favicon.ico -------------------------------------------------------------------------------- /functions/pre-sign-up-trigger/README.md: -------------------------------------------------------------------------------- 1 | # Pre Sign Up Function 2 | 3 | This function is called on the AWS Cognito `preSignUp` event. 4 | -------------------------------------------------------------------------------- /packages/cdk-constructs/README.md: -------------------------------------------------------------------------------- 1 | # CDK Constructs 2 | 3 | This package contains CDK constructs used by the `sst-stacks` package. 4 | -------------------------------------------------------------------------------- /packages/sst-stacks/README.md: -------------------------------------------------------------------------------- 1 | # SST Stacks 2 | 3 | This package contains the SST stacks responsible for provisioning infrastructure on AWS. 4 | -------------------------------------------------------------------------------- /functions/README.md: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 | Contains Lambda functions not accessible over the public network, like Lambda Triggers or Step Functions. 4 | -------------------------------------------------------------------------------- /packages/common/README.md: -------------------------------------------------------------------------------- 1 | # Common 2 | 3 | This package contains utilities and functionality shared across apps, functions, packages and services. 4 | -------------------------------------------------------------------------------- /packages/tsconfig/README.md: -------------------------------------------------------------------------------- 1 | # TSConfig 2 | 3 | This package contains TypeScript configuration shared across apps, functions, packages and services. 4 | -------------------------------------------------------------------------------- /packages/trpc-gateway/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createSiteGatewayLink } from "./lib/links/site"; 2 | export type { SiteRouter } from "./lib/routers/site"; 3 | -------------------------------------------------------------------------------- /packages/trpc-gateway/README.md: -------------------------------------------------------------------------------- 1 | # tRPC Gateway 2 | 3 | This package contains the tRPC configuration responsible for routing requests to the correct service. 4 | -------------------------------------------------------------------------------- /packages/edgedb/scripts/generate-query-builder.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | npx @edgedb/generate edgeql-js --force-overwrite --target ts --output-dir src/lib/queryBuilder -------------------------------------------------------------------------------- /packages/eslint-config-custom/README.md: -------------------------------------------------------------------------------- 1 | # ESLint Config Custon 2 | 3 | This package contains ESLint configuration shared across apps, functions, packages and services. 4 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/lib/utils/crypto.ts: -------------------------------------------------------------------------------- 1 | import crypto from "crypto"; 2 | 3 | export function generateRandomString() { 4 | return crypto.randomBytes(20).toString("hex"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/site/remix.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@remix-run/dev').AppConfig} */ 2 | module.exports = { 3 | serverDependenciesToBundle: [/^@sst-app*/], 4 | ignoredRouteFiles: ["**/.*"], 5 | }; 6 | -------------------------------------------------------------------------------- /services/demo/src/router.ts: -------------------------------------------------------------------------------- 1 | import { createRouter } from "@sst-app/trpc"; 2 | 3 | import { helloWorld } from "./procedures/queries/helloWorld"; 4 | 5 | export const router = createRouter({ 6 | helloWorld, 7 | }); 8 | -------------------------------------------------------------------------------- /packages/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/package-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/edgedb/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/package-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/trpc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/package-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/package-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /services/auth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/service-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /services/demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/service-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/auth-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/package-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/lambda-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/package-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/sst-stacks/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/package-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/trpc-gateway/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/package-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /services/demo/src/procedures/queries/helloWorld.ts: -------------------------------------------------------------------------------- 1 | import { procedure } from "@sst-app/trpc"; 2 | 3 | /** 4 | * Hello World 5 | */ 6 | export const helloWorld = procedure.query(() => { 7 | return { message: "Hello World" }; 8 | }); 9 | -------------------------------------------------------------------------------- /packages/cdk-constructs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/package-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /functions/pre-sign-up-trigger/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/service-preset.json", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | }, 6 | "include": ["./**/*"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/trpc/src/index.ts: -------------------------------------------------------------------------------- 1 | export type { Context } from "./lib/createContext"; 2 | export { createContext } from "./lib/createContext"; 3 | export * from "./lib/init"; 4 | export { awsLambdaRequestHandler } from "@trpc/server/adapters/aws-lambda"; 5 | -------------------------------------------------------------------------------- /apps/site/app/routes/auth/logout.tsx: -------------------------------------------------------------------------------- 1 | import type { LoaderArgs } from "@remix-run/node"; 2 | 3 | import { logoutUser } from "~/server/auth.server"; 4 | 5 | export async function loader({ request }: LoaderArgs) { 6 | await logoutUser(request); 7 | } 8 | -------------------------------------------------------------------------------- /packages/common/src/lib/validation.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export function isEmail(maybeEmail: unknown) { 4 | const emailSchema = z.string().email(); 5 | const { success } = emailSchema.safeParse(maybeEmail); 6 | 7 | return success; 8 | } 9 | -------------------------------------------------------------------------------- /apps/site/app/routes/auth/callback.tsx: -------------------------------------------------------------------------------- 1 | import type { LoaderArgs } from "@remix-run/node"; 2 | 3 | import { authenticateUser } from "~/server/auth.server"; 4 | 5 | export async function loader({ request }: LoaderArgs) { 6 | await authenticateUser(request); 7 | } 8 | -------------------------------------------------------------------------------- /apps/site/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["app/**/*.{ts,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [require("@tailwindcss/forms"), require("@tailwindcss/typography")], 8 | }; 9 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/lib/utils/general.ts: -------------------------------------------------------------------------------- 1 | export function prefixObjectKeys(object: Record, prefix: string) { 2 | return Object.entries(object).reduce( 3 | (acc, [key, value]) => ({ ...acc, [`${prefix}_${key}`]: value }), 4 | {} 5 | ); 6 | } 7 | -------------------------------------------------------------------------------- /packages/edgedb/dbschema/default.esdl: -------------------------------------------------------------------------------- 1 | module default { 2 | type User { 3 | required property email -> str { 4 | constraint exclusive; 5 | } 6 | required property given_name -> str; 7 | required property family_name -> str; 8 | } 9 | } -------------------------------------------------------------------------------- /packages/tsconfig/presets/service-preset.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Service Preset", 4 | "extends": "./base-preset.json", 5 | "compilerOptions": { 6 | "target": "es2020", 7 | "lib": ["esnext"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/site/README.md: -------------------------------------------------------------------------------- 1 | # Site 2 | 3 | The user-facing site. 4 | 5 | ## Developing locally 6 | 7 | Start the app locally: 8 | 9 | ```console 10 | npm run dev 11 | ``` 12 | 13 | > Infrastructure must be provisioned beforehand by running `npm run sst:start` in the root directory. 14 | -------------------------------------------------------------------------------- /services/auth/handlers.ts: -------------------------------------------------------------------------------- 1 | import { awsLambdaRequestHandler, createContext } from "@sst-app/trpc"; 2 | 3 | import { router } from "./src/router"; 4 | 5 | /** 6 | * Main Handler 7 | */ 8 | export const main = awsLambdaRequestHandler({ 9 | router, 10 | createContext, 11 | }); 12 | -------------------------------------------------------------------------------- /services/demo/handlers.ts: -------------------------------------------------------------------------------- 1 | import { awsLambdaRequestHandler, createContext } from "@sst-app/trpc"; 2 | 3 | import { router } from "./src/router"; 4 | 5 | /** 6 | * Main Handler 7 | */ 8 | export const main = awsLambdaRequestHandler({ 9 | router, 10 | createContext, 11 | }); 12 | -------------------------------------------------------------------------------- /apps/site/app/server/session.server.ts: -------------------------------------------------------------------------------- 1 | import { createCookieSessionStorage } from "@remix-run/node"; 2 | 3 | import { sessionCookie } from "./cookies.server"; 4 | 5 | export const { getSession, commitSession, destroySession } = createCookieSessionStorage({ 6 | cookie: sessionCookie, 7 | }); 8 | -------------------------------------------------------------------------------- /services/auth/src/procedures/mutations/credentials.ts: -------------------------------------------------------------------------------- 1 | import { createRouter } from "@sst-app/trpc"; 2 | 3 | import { issue } from "./credentials/issue"; 4 | import { refresh } from "./credentials/refresh"; 5 | 6 | export const credentials = createRouter({ 7 | issue, 8 | refresh, 9 | }); 10 | -------------------------------------------------------------------------------- /services/auth/src/router.ts: -------------------------------------------------------------------------------- 1 | import { createRouter } from "@sst-app/trpc"; 2 | 3 | import { credentials } from "./procedures/mutations/credentials"; 4 | import { userInfo } from "./procedures/queries/userInfo"; 5 | 6 | export const router = createRouter({ 7 | credentials, 8 | userInfo, 9 | }); 10 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # Route53 2 | ROUTE53_ZONE_NAME="" 3 | ROUTE53_HOSTED_ZONE_ID="" 4 | 5 | # EdgeDB 6 | EDGEDB_INSTANCE_COUNT=1 7 | EDGEDB_DOMAIN_NAME="edgedb.$ROUTE53_ZONE_NAME" 8 | 9 | # Site 10 | SITE_DOMAIN_NAME="site.$ROUTE53_ZONE_NAME" 11 | 12 | # Api 13 | API_DOMAIN_NAME="api.$ROUTE53_ZONE_NAME" 14 | -------------------------------------------------------------------------------- /packages/edgedb/dbschema/migrations/00001.edgeql: -------------------------------------------------------------------------------- 1 | CREATE MIGRATION m1l4yvjnhita7ikrqpd52ruclxz3kxhiqorquhlfct2zpdcbp3ehfq 2 | ONTO initial 3 | { 4 | CREATE TYPE default::User { 5 | CREATE REQUIRED PROPERTY family_name -> std::str; 6 | CREATE REQUIRED PROPERTY given_name -> std::str; 7 | }; 8 | }; -------------------------------------------------------------------------------- /packages/tsconfig/presets/package-preset.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Package Preset", 4 | "extends": "./base-preset.json", 5 | "compilerOptions": { 6 | "target": "es2020", 7 | "lib": ["esnext"], 8 | "jsx": "react-jsx" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/tsconfig/presets/vite-app-preset.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Vite App Preset", 4 | "extends": "./base-preset.json", 5 | "compilerOptions": { 6 | "target": "es2020", 7 | "lib": ["dom", "dom.iterable", "esnext"], 8 | "jsx": "react-jsx" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/tsconfig/presets/remix-app-preset.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Remix App Preset", 4 | "extends": "./base-preset.json", 5 | "compilerOptions": { 6 | "target": "es2020", 7 | "lib": ["dom", "dom.iterable", "esnext"], 8 | "jsx": "react-jsx" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/trpc/src/lib/init.ts: -------------------------------------------------------------------------------- 1 | import { initTRPC } from "@trpc/server"; 2 | import superjson from "superjson"; 3 | 4 | import type { Context } from "./createContext"; 5 | 6 | export const { 7 | router: createRouter, 8 | procedure, 9 | middleware, 10 | } = initTRPC.context().create({ 11 | transformer: superjson, 12 | }); 13 | -------------------------------------------------------------------------------- /apps/site/app/utils/env.ts: -------------------------------------------------------------------------------- 1 | export function getGlobalEnvVar(key: keyof typeof env) { 2 | const value = env[key]; 3 | 4 | if (typeof value === "undefined") { 5 | throw new Error(`Missing global environment variable "${key}"`); 6 | } 7 | 8 | return value; 9 | } 10 | 11 | export const isProduction = getGlobalEnvVar("NODE_ENV") === "production"; 12 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/lib/Config.ts: -------------------------------------------------------------------------------- 1 | import type { StackContext } from "@serverless-stack/resources"; 2 | import { Config } from "@serverless-stack/resources"; 3 | 4 | export function ConfigStack({ stack }: StackContext) { 5 | const REGION = new Config.Parameter(stack, "REGION", { 6 | value: stack.region, 7 | }); 8 | 9 | return { REGION }; 10 | } 11 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": ["dist/**"] 7 | }, 8 | "typecheck": { 9 | "outputs": [] 10 | }, 11 | "lint": { 12 | "outputs": [] 13 | }, 14 | "dev": { 15 | "cache": false 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/site/app/routes/index.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "@remix-run/react"; 2 | 3 | export default function Route() { 4 | return ( 5 |
6 |

Welcome to the `site` app

7 | 8 | Go to private route 9 | 10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .build 2 | .sst 3 | dist 4 | 5 | # Dependencies 6 | node_modules 7 | .pnp 8 | .pnp.js 9 | 10 | # Testing 11 | coverage 12 | 13 | # Misc 14 | .DS_Store 15 | *.pem 16 | cdk.context.json 17 | cdk.out 18 | 19 | # Debug 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | .pnpm-debug.log* 24 | 25 | # Environment 26 | .env* 27 | !.env.example 28 | 29 | # Turbo 30 | .turbo 31 | -------------------------------------------------------------------------------- /apps/site/app/utils/trpc.ts: -------------------------------------------------------------------------------- 1 | import { createSiteGatewayLink } from "@sst-app/trpc-gateway"; 2 | import { createTRPCProxyClient } from "@trpc/client"; 3 | import superjson from "superjson"; 4 | 5 | import { getGlobalEnvVar } from "./env"; 6 | 7 | export const trpcClient = createTRPCProxyClient({ 8 | links: [createSiteGatewayLink(getGlobalEnvVar("API_URL"))], 9 | transformer: superjson, 10 | }); 11 | -------------------------------------------------------------------------------- /packages/common/src/lib/constants.ts: -------------------------------------------------------------------------------- 1 | export const MIN_PASSWORD_LENGTH_LAX = 6 as const; 2 | 3 | export const PASSWORD_POLICY_LAX = { 4 | minLength: MIN_PASSWORD_LENGTH_LAX, 5 | requireLowercase: false, 6 | requireUppercase: false, 7 | requireDigits: false, 8 | requireSymbols: false, 9 | } as const; 10 | 11 | export const TRUSTED_EMAIL_DOMAINS = ["gmail.com", "googlemail.com"] as const; 12 | -------------------------------------------------------------------------------- /packages/trpc-gateway/src/lib/routers/site.ts: -------------------------------------------------------------------------------- 1 | import { router as authRouter } from "@sst-app/auth"; 2 | import { router as demoRouter } from "@sst-app/demo"; 3 | import { createRouter } from "@sst-app/trpc"; 4 | 5 | /** 6 | * The router for the `site` app. 7 | */ 8 | const siteRouter = createRouter({ 9 | auth: authRouter, 10 | demo: demoRouter, 11 | }); 12 | 13 | export type SiteRouter = typeof siteRouter; 14 | -------------------------------------------------------------------------------- /packages/trpc-gateway/src/lib/links/site.ts: -------------------------------------------------------------------------------- 1 | import { createGatewayLink } from "../createGatewayLink"; 2 | import type { SiteRouter } from "../routers/site"; 3 | 4 | /** 5 | * Creates the tRPC gateway link for the `site` app. 6 | */ 7 | export function createSiteGatewayLink(baseUrl: string) { 8 | return createGatewayLink({ 9 | auth: `${baseUrl}auth`, 10 | demo: `${baseUrl}demo`, 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /packages/edgedb/dbschema/migrations/00002.edgeql: -------------------------------------------------------------------------------- 1 | CREATE MIGRATION m134igsw5sl6ttocc6bglu3a445p3opb7bjjj6yjsfdddep6vlmacq 2 | ONTO m1l4yvjnhita7ikrqpd52ruclxz3kxhiqorquhlfct2zpdcbp3ehfq 3 | { 4 | ALTER TYPE default::User { 5 | CREATE REQUIRED PROPERTY email -> std::str { 6 | SET REQUIRED USING ('l.seipp@microeinhundert.com'); 7 | CREATE CONSTRAINT std::exclusive; 8 | }; 9 | }; 10 | }; 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug SST Start", 6 | "type": "node", 7 | "request": "launch", 8 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/sst", 9 | "runtimeArgs": ["start", "--increase-timeout"], 10 | "console": "integratedTerminal", 11 | "skipFiles": ["/**"], 12 | "env": {} 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/lib/env/formatErrors.ts: -------------------------------------------------------------------------------- 1 | import type { ZodFormattedError } from "zod"; 2 | 3 | export function formatErrors(errors: ZodFormattedError, string>) { 4 | return Object.entries(errors) 5 | .map(([name, value]) => { 6 | if (value && "_errors" in value) { 7 | return `${name}: ${value._errors.join(", ")}\n`; 8 | } 9 | return false; 10 | }) 11 | .filter(Boolean); 12 | } 13 | -------------------------------------------------------------------------------- /packages/lambda-utils/src/lib/getSecretValue.ts: -------------------------------------------------------------------------------- 1 | import { SecretsManager } from "@aws-sdk/client-secrets-manager"; 2 | import { Config } from "@serverless-stack/node/config"; 3 | 4 | const secretsManager = new SecretsManager({ region: Config.REGION }); 5 | 6 | export async function getSecretValue(secretId: string) { 7 | const secretValue = await secretsManager.getSecretValue({ 8 | SecretId: secretId, 9 | }); 10 | 11 | return secretValue.SecretString ?? ""; 12 | } 13 | -------------------------------------------------------------------------------- /services/auth/src/validators/userInfo.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const userInfoInputSchema = z.object({ 4 | accessToken: z.string().min(1), 5 | }); 6 | 7 | export const userInfoOutputSchema = z.object({ 8 | sub: z.string().min(1), 9 | email: z.string().email(), 10 | username: z.string().min(1), 11 | }); 12 | 13 | export type UserInfoInput = z.infer; 14 | export type UserInfoOutput = z.infer; 15 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/lib/env/index.ts: -------------------------------------------------------------------------------- 1 | import { formatErrors } from "./formatErrors"; 2 | import { schema } from "./schema"; 3 | 4 | const schemaParseResult = schema.safeParse(process.env); 5 | 6 | if (!schemaParseResult.success) { 7 | console.error( 8 | "❌ Invalid environment variables:\n", 9 | ...formatErrors(schemaParseResult.error.format()) 10 | ); 11 | 12 | throw new Error("Invalid environment variables"); 13 | } 14 | 15 | export const env = schemaParseResult.data; 16 | -------------------------------------------------------------------------------- /packages/edgedb/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Config } from "@serverless-stack/node/config"; 2 | import { getSecretValue } from "@sst-app/lambda-utils"; 3 | 4 | // @ts-ignore: Generated 5 | import e, { Cardinality, createClient } from "./lib/queryBuilder"; 6 | 7 | const connection = JSON.parse(await getSecretValue(Config.EDGEDB_CONNECTION_SECRET_ARN)) as { 8 | dsn: string; 9 | }; 10 | 11 | const client = createClient({ 12 | dsn: connection.dsn, 13 | tlsSecurity: "insecure", 14 | }); 15 | 16 | export { Cardinality, client, e }; 17 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/lib/env/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | /** 4 | * Specify your SST environment variables schema here. 5 | * This way you can ensure the infrastructure can't be provisioned with invalid environment variables. 6 | */ 7 | export const schema = z.object({ 8 | ROUTE53_ZONE_NAME: z.string(), 9 | ROUTE53_HOSTED_ZONE_ID: z.string(), 10 | 11 | EDGEDB_INSTANCE_COUNT: z.string(), 12 | EDGEDB_DOMAIN_NAME: z.string(), 13 | 14 | SITE_DOMAIN_NAME: z.string(), 15 | API_DOMAIN_NAME: z.string(), 16 | }); 17 | -------------------------------------------------------------------------------- /services/auth/src/validators/refreshCredentials.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const refreshCredentialsInputSchema = z.object({ 4 | redirectUri: z.string().min(1), 5 | refreshToken: z.string().min(1), 6 | }); 7 | 8 | export const refreshCredentialsOutputSchema = z.object({ 9 | access_token: z.string().min(1), 10 | id_token: z.string().min(1), 11 | expires_in: z.number(), 12 | }); 13 | 14 | export type RefreshCredentialsInput = z.infer; 15 | export type RefreshCredentialsOutput = z.infer; 16 | -------------------------------------------------------------------------------- /services/auth/src/validators/issueCredentials.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const issueCredentialsInputSchema = z.object({ 4 | redirectUri: z.string().min(1), 5 | code: z.string().min(1), 6 | }); 7 | 8 | export const issueCredentialsOutputSchema = z.object({ 9 | access_token: z.string().min(1), 10 | refresh_token: z.string().min(1), 11 | id_token: z.string().min(1), 12 | expires_in: z.number(), 13 | }); 14 | 15 | export type IssueCredentialsInput = z.infer; 16 | export type IssueCredentialsOutput = z.infer; 17 | -------------------------------------------------------------------------------- /apps/site/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sst-app/tsconfig/presets/remix-app-preset.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "forceConsistentCasingInFileNames": true, 6 | "lib": ["dom", "dom.iterable", "es2019"], 7 | "strict": true, 8 | "target": "es2019", 9 | "esModuleInterop": true, 10 | "isolatedModules": true, 11 | "jsx": "react-jsx", 12 | "moduleResolution": "node", 13 | "noEmit": true, 14 | "resolveJsonModule": true, 15 | "baseUrl": ".", 16 | "paths": { 17 | "~/*": ["app/*"] 18 | } 19 | }, 20 | "include": ["app/**/*"] 21 | } 22 | -------------------------------------------------------------------------------- /apps/site/app/entry.client.tsx: -------------------------------------------------------------------------------- 1 | import { RemixBrowser } from "@remix-run/react"; 2 | import { startTransition, StrictMode } from "react"; 3 | import { hydrateRoot } from "react-dom/client"; 4 | 5 | function hydrate() { 6 | startTransition(() => { 7 | hydrateRoot( 8 | document, 9 | 10 | 11 | 12 | ); 13 | }); 14 | } 15 | 16 | if (window.requestIdleCallback) { 17 | window.requestIdleCallback(hydrate); 18 | } else { 19 | // Safari doesn't support requestIdleCallback 20 | // https://caniuse.com/requestidlecallback 21 | window.setTimeout(hydrate, 1); 22 | } 23 | -------------------------------------------------------------------------------- /apps/site/app/entry.server.tsx: -------------------------------------------------------------------------------- 1 | import type { EntryContext } from "@remix-run/node"; 2 | import { RemixServer } from "@remix-run/react"; 3 | import { renderToString } from "react-dom/server"; 4 | 5 | export default function handleRequest( 6 | request: Request, 7 | responseStatusCode: number, 8 | responseHeaders: Headers, 9 | remixContext: EntryContext 10 | ) { 11 | const markup = renderToString(); 12 | 13 | responseHeaders.set("Content-Type", "text/html"); 14 | 15 | return new Response("" + markup, { 16 | status: responseStatusCode, 17 | headers: responseHeaders, 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /services/auth/src/procedures/queries/userInfo.ts: -------------------------------------------------------------------------------- 1 | import { Config } from "@serverless-stack/node/config"; 2 | import { procedure } from "@sst-app/trpc"; 3 | 4 | import { fetchCognito } from "../../utils/fetchCognito"; 5 | import { userInfoInputSchema, userInfoOutputSchema } from "../../validators/userInfo"; 6 | 7 | /** 8 | * User Info 9 | */ 10 | export const userInfo = procedure 11 | .input(userInfoInputSchema) 12 | .output(userInfoOutputSchema) 13 | .query(async ({ input }) => { 14 | return fetchCognito(`${Config.COGNITO_BASE_URL}/oauth2/userInfo`, { 15 | method: "GET", 16 | headers: { 17 | Authorization: `Bearer ${input.accessToken}`, 18 | }, 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/lib/App.ts: -------------------------------------------------------------------------------- 1 | import type { App } from "@serverless-stack/resources"; 2 | 3 | import { ApiStack } from "./Api"; 4 | import { AppsStack } from "./Apps"; 5 | import { AuthStack } from "./Auth"; 6 | import { ConfigStack } from "./Config"; 7 | import { PersistenceStack } from "./Persistence"; 8 | import { ServicesStack } from "./Services"; 9 | 10 | export default function (app: App) { 11 | app.setDefaultFunctionProps({ 12 | runtime: "nodejs16.x", 13 | timeout: 10, 14 | bundle: { 15 | format: "esm", 16 | }, 17 | }); 18 | 19 | app 20 | .stack(ConfigStack) 21 | .stack(PersistenceStack) 22 | .stack(AuthStack) 23 | .stack(ApiStack) 24 | .stack(ServicesStack) 25 | .stack(AppsStack); 26 | } 27 | -------------------------------------------------------------------------------- /packages/tsconfig/presets/base-preset.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Base Preset", 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "composite": false, 7 | "declaration": false, 8 | "declarationMap": false, 9 | "esModuleInterop": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "inlineSources": false, 12 | "isolatedModules": true, 13 | "module": "esnext", 14 | "moduleResolution": "node", 15 | "noUnusedLocals": false, 16 | "noUnusedParameters": false, 17 | "preserveWatchOutput": true, 18 | "skipLibCheck": true, 19 | "noEmit": true, 20 | "resolveJsonModule": true, 21 | "strict": true, 22 | "downlevelIteration": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/edgedb/scripts/link.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | APP_NAME="sst_app" 4 | 5 | # Install the EdgeDB CLI if not already installed 6 | if ! [[ "$(which edgedb)" ]]; then 7 | curl --proto '=https' --tlsv1.2 -sSf https://sh.edgedb.com | sh 8 | fi 9 | 10 | SECRET_ARN=$( 11 | aws secretsmanager list-secrets \ 12 | --filter Key="name",Values="EdgeDBConnection" \ 13 | | jq --raw-output ".SecretList" \ 14 | | jq -r ".[0].ARN" 15 | ) 16 | 17 | DSN=$( 18 | aws secretsmanager get-secret-value \ 19 | --secret-id $SECRET_ARN \ 20 | | jq --raw-output ".SecretString" \ 21 | | jq -r ".dsn" 22 | ) 23 | 24 | edgedb instance link \ 25 | --non-interactive \ 26 | --trust-tls-cert \ 27 | --overwrite \ 28 | --dsn $DSN \ 29 | $APP_NAME -------------------------------------------------------------------------------- /services/auth/validators.ts: -------------------------------------------------------------------------------- 1 | // IssueCredentials 2 | export type { 3 | IssueCredentialsInput, 4 | IssueCredentialsOutput, 5 | } from "./src/validators/issueCredentials"; 6 | export { 7 | issueCredentialsInputSchema, 8 | issueCredentialsOutputSchema, 9 | } from "./src/validators/issueCredentials"; 10 | 11 | // RefreshCredentials 12 | export type { 13 | RefreshCredentialsInput, 14 | RefreshCredentialsOutput, 15 | } from "./src/validators/refreshCredentials"; 16 | export { 17 | refreshCredentialsInputSchema, 18 | refreshCredentialsOutputSchema, 19 | } from "./src/validators/refreshCredentials"; 20 | 21 | // UserInfo 22 | export type { UserInfoInput, UserInfoOutput } from "./src/validators/userInfo"; 23 | export { userInfoInputSchema, userInfoOutputSchema } from "./src/validators/userInfo"; 24 | -------------------------------------------------------------------------------- /functions/pre-sign-up-trigger/handlers.ts: -------------------------------------------------------------------------------- 1 | import { TRUSTED_EMAIL_DOMAINS } from "@sst-app/common"; 2 | import { client, e } from "@sst-app/edgedb"; 3 | import type { PreSignUpTriggerHandler } from "aws-lambda"; 4 | 5 | /** 6 | * Main Handler 7 | */ 8 | export const main: PreSignUpTriggerHandler = async (event) => { 9 | const { email, given_name, family_name } = event.request.userAttributes; 10 | 11 | await e 12 | .insert(e.User, { 13 | email: e.str(email), 14 | given_name: e.str(given_name), 15 | family_name: e.str(family_name), 16 | }) 17 | .run(client); 18 | 19 | // Automatically confirm users who are using 20 | // one of the trusted email domains 21 | event.response.autoConfirmUser = TRUSTED_EMAIL_DOMAINS.some((domain) => email.endsWith(domain)); 22 | 23 | return event; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/lib/utils/auth.ts: -------------------------------------------------------------------------------- 1 | import { env } from "../env"; 2 | 3 | export function getAuthCallbackUrls(isDevStage?: boolean) { 4 | let callbackUrls = [env.SITE_DOMAIN_NAME].map( 5 | (domainName) => `https://${domainName}/auth/callback/` 6 | ); 7 | 8 | if (isDevStage) { 9 | // 3000 = Site App 10 | const devCallbackUrls = [3000].map((port) => `http://localhost:${port}/auth/callback/`); 11 | callbackUrls = [...callbackUrls, devCallbackUrls].flat(); 12 | } 13 | 14 | return callbackUrls; 15 | } 16 | 17 | export function getAuthLogoutUrls(isDevStage?: boolean) { 18 | let logoutUrls = [env.SITE_DOMAIN_NAME].map((domainName) => `https://${domainName}/auth/logout/`); 19 | 20 | if (isDevStage) { 21 | // 3000 = Site App 22 | const devLogoutUrls = [3000].map((port) => `http://localhost:${port}/auth/logout/`); 23 | logoutUrls = [...logoutUrls, devLogoutUrls].flat(); 24 | } 25 | 26 | return logoutUrls; 27 | } 28 | -------------------------------------------------------------------------------- /apps/site/app/routes/private.tsx: -------------------------------------------------------------------------------- 1 | import type { DataFunctionArgs } from "@remix-run/node"; 2 | import { json } from "@remix-run/node"; 3 | import { Link, useLoaderData } from "@remix-run/react"; 4 | 5 | import { ensureUserAuthenticated } from "~/server/auth.server"; 6 | import { trpcClient } from "~/utils/trpc"; 7 | 8 | export async function loader({ request }: DataFunctionArgs) { 9 | const user = await ensureUserAuthenticated(request); 10 | const helloWorld = await trpcClient.demo.helloWorld.query(); 11 | 12 | return json({ 13 | user, 14 | helloWorld, 15 | }); 16 | } 17 | 18 | export default function Route() { 19 | const data = useLoaderData(); 20 | 21 | return ( 22 |
23 |

Welcome, {data.user?.email}

24 |

{data.helloWorld.message}

25 | 26 | Log Out 27 | 28 |
29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /packages/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/tsconfig", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "packages/tsconfig" 9 | }, 10 | "sideEffects": false, 11 | "type": "commonjs", 12 | "exports": { 13 | ".": { 14 | "default": "./src/index.js" 15 | }, 16 | "./presets/package-preset.json": { 17 | "default": "./presets/package-preset.json" 18 | }, 19 | "./presets/remix-app-preset.json": { 20 | "default": "./presets/remix-app-preset.json" 21 | }, 22 | "./presets/service-preset.json": { 23 | "default": "./presets/service-preset.json" 24 | }, 25 | "./presets/vite-app-preset.json": { 26 | "default": "./presets/vite-app-preset.json" 27 | } 28 | }, 29 | "main": "./src/index.js", 30 | "dependencies": { 31 | "typescript": "^4.9.4" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/eslint-config-custom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/eslint-config-custom", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "packages/eslint-config-custom" 9 | }, 10 | "sideEffects": false, 11 | "type": "commonjs", 12 | "exports": { 13 | ".": { 14 | "default": "./src/index.js" 15 | } 16 | }, 17 | "main": "./src/index.js", 18 | "dependencies": { 19 | "@typescript-eslint/eslint-plugin": "^5.47.0", 20 | "@typescript-eslint/parser": "^5.47.0", 21 | "eslint": "^8.30.0", 22 | "eslint-config-prettier": "^8.5.0", 23 | "eslint-config-turbo": "^0.0.7", 24 | "eslint-import-resolver-typescript": "^3.5.2", 25 | "eslint-plugin-import": "2.26.0", 26 | "eslint-plugin-react": "^7.31.11", 27 | "eslint-plugin-react-hooks": "^4.6.0", 28 | "eslint-plugin-simple-import-sort": "^8.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /services/auth/src/procedures/mutations/credentials/issue.ts: -------------------------------------------------------------------------------- 1 | import { Config } from "@serverless-stack/node/config"; 2 | import { procedure } from "@sst-app/trpc"; 3 | 4 | import { fetchCognito } from "../../../utils/fetchCognito"; 5 | import { 6 | issueCredentialsInputSchema, 7 | issueCredentialsOutputSchema, 8 | } from "../../../validators/issueCredentials"; 9 | 10 | /** 11 | * Issue 12 | */ 13 | export const issue = procedure 14 | .input(issueCredentialsInputSchema) 15 | .output(issueCredentialsOutputSchema) 16 | .mutation(async ({ input }) => { 17 | return fetchCognito(`${Config.COGNITO_BASE_URL}/oauth2/token`, { 18 | method: "POST", 19 | headers: { 20 | "Content-Type": "application/x-www-form-urlencoded", 21 | }, 22 | body: new URLSearchParams({ 23 | grant_type: "authorization_code", 24 | client_id: Config.COGNITO_USER_POOL_CLIENT_ID, 25 | redirect_uri: input.redirectUri, 26 | code: input.code, 27 | }), 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /services/auth/src/utils/fetchCognito.ts: -------------------------------------------------------------------------------- 1 | import { TRPCError } from "@trpc/server"; 2 | import type { RequestInfo, RequestInit } from "undici"; 3 | import { fetch } from "undici"; 4 | 5 | export async function fetchCognito(input: RequestInfo, init?: RequestInit) { 6 | try { 7 | const response = await fetch(input, init); 8 | 9 | if (response.status !== 200) { 10 | throw new Error("Unexpected response returned by Cognito", { 11 | cause: new Error(response.statusText), 12 | }); 13 | } 14 | 15 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 16 | return (await response.json()) as any; 17 | } catch (error) { 18 | if (error instanceof Error) { 19 | throw new TRPCError({ 20 | code: "INTERNAL_SERVER_ERROR", 21 | message: error.message, 22 | cause: error, 23 | }); 24 | } 25 | 26 | throw new TRPCError({ 27 | code: "INTERNAL_SERVER_ERROR", 28 | message: "An unknown error occurred in the auth service", 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /services/auth/src/procedures/mutations/credentials/refresh.ts: -------------------------------------------------------------------------------- 1 | import { Config } from "@serverless-stack/node/config"; 2 | import { procedure } from "@sst-app/trpc"; 3 | 4 | import { fetchCognito } from "../../../utils/fetchCognito"; 5 | import { 6 | refreshCredentialsInputSchema, 7 | refreshCredentialsOutputSchema, 8 | } from "../../../validators/refreshCredentials"; 9 | 10 | /** 11 | * Refresh 12 | */ 13 | export const refresh = procedure 14 | .input(refreshCredentialsInputSchema) 15 | .output(refreshCredentialsOutputSchema) 16 | .mutation(async ({ input }) => { 17 | return fetchCognito(`${Config.COGNITO_BASE_URL}/oauth2/token`, { 18 | method: "POST", 19 | headers: { 20 | "Content-Type": "application/x-www-form-urlencoded", 21 | }, 22 | body: new URLSearchParams({ 23 | grant_type: "refresh_token", 24 | client_id: Config.COGNITO_USER_POOL_CLIENT_ID, 25 | redirect_uri: input.redirectUri, 26 | refresh_token: input.refreshToken, 27 | }), 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /packages/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/common", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "packages/common" 9 | }, 10 | "sideEffects": false, 11 | "type": "module", 12 | "exports": { 13 | ".": { 14 | "default": "./src/index.ts", 15 | "types": "./src/index.ts" 16 | } 17 | }, 18 | "main": "./src/index.ts", 19 | "types": "./src/index.ts", 20 | "scripts": { 21 | "lint": "TIMING=1 eslint . --ext=.ts,.tsx", 22 | "typecheck": "tsc --noEmit" 23 | }, 24 | "lint-staged": { 25 | "*.{ts,tsx}": [ 26 | "npm run lint -- --fix" 27 | ] 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "@sst-app/eslint-config-custom" 32 | ], 33 | "root": true 34 | }, 35 | "dependencies": { 36 | "zod": "^3.20.2" 37 | }, 38 | "devDependencies": { 39 | "@sst-app/eslint-config-custom": "*", 40 | "@sst-app/tsconfig": "*" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/sst-stacks/src/lib/Api.ts: -------------------------------------------------------------------------------- 1 | import type { StackContext } from "@serverless-stack/resources"; 2 | import { Api, use } from "@serverless-stack/resources"; 3 | 4 | import { AuthStack } from "./Auth"; 5 | import { env } from "./env"; 6 | import { getCorsConfig } from "./utils/api"; 7 | 8 | export function ApiStack({ stack }: StackContext) { 9 | const { cognito } = use(AuthStack); 10 | 11 | const api = new Api(stack, "Api", { 12 | cors: getCorsConfig(stack.stage === "dev"), 13 | customDomain: { 14 | domainName: env.API_DOMAIN_NAME, 15 | hostedZone: env.ROUTE53_ZONE_NAME, 16 | path: "v1", 17 | }, 18 | authorizers: { 19 | jwt: { 20 | type: "user_pool", 21 | userPool: { 22 | id: cognito.userPoolId, 23 | clientIds: [cognito.userPoolClientId], 24 | }, 25 | }, 26 | }, 27 | defaults: { 28 | authorizer: "jwt", 29 | }, 30 | }); 31 | 32 | cognito.attachPermissionsForAuthUsers(stack, [api]); 33 | 34 | const apiUrl = api.customDomainUrl ?? api.url; 35 | 36 | stack.addOutputs({ 37 | ApiEndpoint: apiUrl, 38 | }); 39 | 40 | return { api, apiUrl }; 41 | } 42 | -------------------------------------------------------------------------------- /packages/trpc/src/lib/createContext.ts: -------------------------------------------------------------------------------- 1 | import { CognitoIdentityProviderClient } from "@aws-sdk/client-cognito-identity-provider"; 2 | import { Config } from "@serverless-stack/node/config"; 3 | import { client as edgeDBClient } from "@sst-app/edgedb"; 4 | import type { inferAsyncReturnType } from "@trpc/server"; 5 | import type { CreateAWSLambdaContextOptions } from "@trpc/server/adapters/aws-lambda"; 6 | import type { APIGatewayProxyEventV2WithJWTAuthorizer } from "aws-lambda"; 7 | 8 | export const cognitoClient = new CognitoIdentityProviderClient({ region: Config.REGION }); 9 | 10 | export const createContext = ({ 11 | event, 12 | context, 13 | }: CreateAWSLambdaContextOptions) => { 14 | // Add data from the request context here, 15 | // for example the currently authenticated user 16 | const scopedEdgeDBClient = edgeDBClient.withGlobals({ 17 | current_user_email: "", 18 | }); 19 | 20 | return { 21 | db: scopedEdgeDBClient, 22 | auth: cognitoClient, 23 | lambdaEvent: event, 24 | lambdaContext: context, 25 | }; 26 | }; 27 | 28 | export type Context = inferAsyncReturnType; 29 | -------------------------------------------------------------------------------- /packages/cdk-constructs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/cdk-constructs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "packages/cdk-constructs" 9 | }, 10 | "sideEffects": false, 11 | "type": "module", 12 | "exports": { 13 | ".": { 14 | "default": "./src/index.ts", 15 | "types": "./src/index.ts" 16 | } 17 | }, 18 | "main": "./src/index.ts", 19 | "types": "./src/index.ts", 20 | "scripts": { 21 | "lint": "TIMING=1 eslint . --ext=.ts,.tsx", 22 | "typecheck": "tsc --noEmit" 23 | }, 24 | "lint-staged": { 25 | "*.{ts,tsx}": [ 26 | "npm run lint -- --fix" 27 | ] 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "@sst-app/eslint-config-custom" 32 | ], 33 | "root": true 34 | }, 35 | "dependencies": { 36 | "aws-cdk-lib": "2.39.1", 37 | "constructs": "^10.1.194" 38 | }, 39 | "devDependencies": { 40 | "@sst-app/eslint-config-custom": "*", 41 | "@sst-app/tsconfig": "*", 42 | "@types/node": "^16" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/types", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "packages/types" 9 | }, 10 | "sideEffects": false, 11 | "type": "module", 12 | "exports": { 13 | ".": { 14 | "default": "./src/index.ts", 15 | "types": "./src/index.ts" 16 | } 17 | }, 18 | "main": "./src/index.ts", 19 | "types": "./src/index.ts", 20 | "scripts": { 21 | "lint": "TIMING=1 eslint . --ext=.ts,.tsx", 22 | "typecheck": "tsc --noEmit" 23 | }, 24 | "lint-staged": { 25 | "*.{ts,tsx}": [ 26 | "npm run lint -- --fix" 27 | ] 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "@sst-app/eslint-config-custom" 32 | ], 33 | "root": true 34 | }, 35 | "dependencies": { 36 | "@aws-sdk/client-secrets-manager": "^3.231.0", 37 | "@serverless-stack/node": "^1.18.4" 38 | }, 39 | "devDependencies": { 40 | "@sst-app/eslint-config-custom": "*", 41 | "@sst-app/tsconfig": "*", 42 | "@types/node": "^16" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/lambda-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/lambda-utils", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "packages/lambda-utils" 9 | }, 10 | "sideEffects": false, 11 | "type": "module", 12 | "exports": { 13 | ".": { 14 | "default": "./src/index.ts", 15 | "types": "./src/index.ts" 16 | } 17 | }, 18 | "main": "./src/index.ts", 19 | "types": "./src/index.ts", 20 | "scripts": { 21 | "lint": "TIMING=1 eslint . --ext=.ts,.tsx", 22 | "typecheck": "tsc --noEmit" 23 | }, 24 | "lint-staged": { 25 | "*.{ts,tsx}": [ 26 | "npm run lint -- --fix" 27 | ] 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "@sst-app/eslint-config-custom" 32 | ], 33 | "root": true 34 | }, 35 | "dependencies": { 36 | "@aws-sdk/client-secrets-manager": "^3.231.0", 37 | "@serverless-stack/node": "^1.18.4" 38 | }, 39 | "devDependencies": { 40 | "@sst-app/eslint-config-custom": "*", 41 | "@sst-app/tsconfig": "*", 42 | "@types/node": "^16" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /apps/site/app/server/cookies.server.ts: -------------------------------------------------------------------------------- 1 | import { createCookie } from "@remix-run/node"; 2 | 3 | import { getEnvVar } from "~/server/env.server"; 4 | import { isProduction } from "~/utils/env"; 5 | 6 | export const sessionCookie = createCookie("session", { 7 | domain: isProduction ? getEnvVar("DOMAIN_NAME") : undefined, 8 | maxAge: 1000 * 60 * 60 * 24 * 60, // 60 Days 9 | secure: isProduction, 10 | sameSite: isProduction ? "strict" : "lax", 11 | secrets: [getEnvVar("SESSION_SECRET")], 12 | httpOnly: true, 13 | }); 14 | 15 | export const accessTokenCookie = createCookie("access_token", { 16 | domain: isProduction ? getEnvVar("DOMAIN_NAME") : undefined, 17 | maxAge: 1000 * 60 * 60 * 24 * 60, // 60 Days 18 | secure: isProduction, 19 | sameSite: isProduction ? "strict" : "lax", 20 | secrets: [getEnvVar("SESSION_SECRET")], 21 | httpOnly: true, 22 | }); 23 | 24 | export const refreshTokenCookie = createCookie("refresh_token", { 25 | domain: isProduction ? getEnvVar("DOMAIN_NAME") : undefined, 26 | maxAge: 1000 * 60 * 60 * 24 * 60, // 60 Days 27 | secure: isProduction, 28 | sameSite: isProduction ? "strict" : "lax", 29 | secrets: [getEnvVar("SESSION_SECRET")], 30 | httpOnly: true, 31 | }); 32 | -------------------------------------------------------------------------------- /packages/auth-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/auth-utils", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "packages/auth-utils" 9 | }, 10 | "sideEffects": false, 11 | "type": "module", 12 | "exports": { 13 | ".": { 14 | "default": "./src/index.ts", 15 | "types": "./src/index.ts" 16 | } 17 | }, 18 | "main": "./src/index.ts", 19 | "types": "./src/index.ts", 20 | "scripts": { 21 | "lint": "TIMING=1 eslint . --ext=.ts,.tsx", 22 | "typecheck": "tsc --noEmit" 23 | }, 24 | "lint-staged": { 25 | "*.{ts,tsx}": [ 26 | "npm run lint -- --fix" 27 | ] 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "@sst-app/eslint-config-custom" 32 | ], 33 | "root": true 34 | }, 35 | "dependencies": { 36 | "@aws-sdk/client-secrets-manager": "^3.231.0", 37 | "@serverless-stack/node": "^1.18.4" 38 | }, 39 | "devDependencies": { 40 | "@sst-app/eslint-config-custom": "*", 41 | "@sst-app/tsconfig": "*", 42 | "@sst-app/types": "*", 43 | "@types/node": "^16" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/trpc-gateway/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/trpc-gateway", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "packages/trpc-gateway" 9 | }, 10 | "sideEffects": false, 11 | "type": "module", 12 | "exports": { 13 | ".": { 14 | "default": "./src/index.ts", 15 | "types": "./src/index.ts" 16 | } 17 | }, 18 | "main": "./src/index.ts", 19 | "types": "./src/index.ts", 20 | "scripts": { 21 | "lint": "TIMING=1 eslint . --ext=.ts,.tsx", 22 | "typecheck": "tsc --noEmit" 23 | }, 24 | "lint-staged": { 25 | "*.{ts,tsx}": [ 26 | "npm run lint -- --fix" 27 | ] 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "@sst-app/eslint-config-custom" 32 | ], 33 | "root": true 34 | }, 35 | "dependencies": { 36 | "@sst-app/demo": "*", 37 | "@sst-app/auth": "*", 38 | "@sst-app/trpc": "*", 39 | "@trpc/client": "10.5.0", 40 | "@trpc/server": "10.5.0" 41 | }, 42 | "devDependencies": { 43 | "@sst-app/eslint-config-custom": "*", 44 | "@sst-app/tsconfig": "*" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/sst-stacks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/sst-stacks", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "packages/sst-stacks" 9 | }, 10 | "sideEffects": false, 11 | "type": "module", 12 | "exports": { 13 | ".": { 14 | "default": "./src/index.ts", 15 | "types": "./src/index.ts" 16 | } 17 | }, 18 | "main": "./src/index.ts", 19 | "types": "./src/index.ts", 20 | "scripts": { 21 | "lint": "TIMING=1 eslint . --ext=.ts,.tsx", 22 | "typecheck": "tsc --noEmit" 23 | }, 24 | "lint-staged": { 25 | "*.{ts,tsx}": [ 26 | "npm run lint -- --fix" 27 | ] 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "@sst-app/eslint-config-custom" 32 | ], 33 | "root": true 34 | }, 35 | "dependencies": { 36 | "@serverless-stack/resources": "1.18.4", 37 | "@sst-app/cdk-constructs": "*", 38 | "@sst-app/common": "*", 39 | "aws-cdk-lib": "2.39.1", 40 | "zod": "^3.20.2" 41 | }, 42 | "devDependencies": { 43 | "@sst-app/eslint-config-custom": "*", 44 | "@sst-app/tsconfig": "*", 45 | "@types/node": "^16" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /functions/pre-sign-up-trigger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sst-app/pre-sign-up-trigger", 3 | "version": "0.0.0", 4 | "private": true, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/microeinhundert/sst-edgedb-trpc-microservices.git", 8 | "directory": "functions/pre-sign-up-trigger" 9 | }, 10 | "type": "module", 11 | "main": "./index.ts", 12 | "types": "./index.ts", 13 | "exports": { 14 | ".": { 15 | "default": "./index.ts", 16 | "types": "./index.ts" 17 | }, 18 | "./handlers": { 19 | "default": "./handlers.ts", 20 | "types": "./handlers.ts" 21 | } 22 | }, 23 | "scripts": { 24 | "lint": "TIMING=1 eslint . --ext=.ts,.tsx", 25 | "typecheck": "tsc --noEmit" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "@sst-app/eslint-config-custom" 30 | ], 31 | "root": true 32 | }, 33 | "lint-staged": { 34 | "*.{ts,tsx}": [ 35 | "npm run lint -- --fix" 36 | ] 37 | }, 38 | "dependencies": { 39 | "@sst-app/common": "*", 40 | "@sst-app/edgedb": "*" 41 | }, 42 | "devDependencies": { 43 | "@sst-app/eslint-config-custom": "*", 44 | "@sst-app/tsconfig": "*", 45 | "@types/aws-lambda": "^8.10.109", 46 | "@types/node": "^16" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /apps/site/app/root.tsx: -------------------------------------------------------------------------------- 1 | import type { LinksFunction, MetaFunction } from "@remix-run/node"; 2 | import { json } from "@remix-run/node"; 3 | import { 4 | Links, 5 | LiveReload, 6 | Meta, 7 | Outlet, 8 | Scripts, 9 | ScrollRestoration, 10 | useLoaderData, 11 | } from "@remix-run/react"; 12 | 13 | import { globalEnv } from "~/server/env.server"; 14 | import styles from "~/styles/app-compiled.css"; 15 | 16 | export const links: LinksFunction = () => [{ rel: "stylesheet", href: styles }]; 17 | 18 | export const meta: MetaFunction = () => ({ 19 | charset: "utf-8", 20 | title: "Site", 21 | viewport: "width=device-width,initial-scale=1", 22 | }); 23 | 24 | export function loader() { 25 | return json({ 26 | env: globalEnv, 27 | }); 28 | } 29 | 30 | export default function App() { 31 | const data = useLoaderData(); 32 | 33 | return ( 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |