Project Structure
Prerequisites: Node.js 22+, npm
Overview
Section titled βOverviewβJaypie projects use npm workspaces in a monorepo structure with shared configuration for TypeScript, ESLint, Vitest, and Vite.
Directory Structure
Section titled βDirectory Structureβproject/βββ .github/β βββ workflows/ # CI/CD workflowsβββ packages/β βββ api/ # Express API packageβ βββ cdk/ # CDK infrastructureβ βββ worker/ # Lambda workersβ βββ shared/ # Shared utilitiesβββ eslint.config.mjs # Root ESLint configβββ lerna.json # Lerna configurationβββ package.json # Root package.jsonβββ tsconfig.json # Root TypeScript configβββ vitest.config.ts # Root Vitest configRoot Configuration
Section titled βRoot Configurationβpackage.json
Section titled βpackage.jsonβ{ "name": "my-project", "version": "0.0.1", "private": true, "type": "module", "workspaces": [ "packages/*" ], "scripts": { "build": "lerna run build", "clean": "lerna run clean", "format": "eslint . --fix", "format:package": "sort-package-json package.json packages/*/package.json", "lint": "eslint .", "test": "vitest run", "typecheck": "lerna run typecheck" }, "devDependencies": { "@jaypie/eslint": "latest", "@jaypie/repokit": "latest", "@jaypie/testkit": "latest", "eslint": "^10.0.0", "lerna": "^8.0.0", "typescript": "^5.0.0", "vite": "^5.0.0", "vitest": "^2.0.0" }}lerna.json
Section titled βlerna.jsonβ{ "$schema": "node_modules/lerna/schemas/lerna-schema.json", "version": "independent", "npmClient": "npm"}eslint.config.mjs
Section titled βeslint.config.mjsβexport { default as default } from "@jaypie/eslint";tsconfig.json
Section titled βtsconfig.jsonβ{ "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "declaration": true, "declarationMap": true, "outDir": "./dist", "rootDir": "./src" }, "exclude": ["node_modules", "dist"]}vitest.config.ts
Section titled βvitest.config.tsβimport { defineConfig } from "vitest/config";
export default defineConfig({ test: { projects: [ "packages/api", "packages/worker", "packages/shared", ], },});Package Configuration
Section titled βPackage ConfigurationβPackage package.json
Section titled βPackage package.jsonβ{ "name": "@project/api", "version": "0.0.1", "type": "module", "private": true, "main": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" } }, "scripts": { "build": "vite build && tsc --emitDeclarationOnly", "clean": "rimraf dist", "test": "vitest run", "typecheck": "tsc --noEmit" }}Package tsconfig.json
Section titled βPackage tsconfig.jsonβ{ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"]}Package vite.config.ts
Section titled βPackage vite.config.tsβimport { defineConfig } from "vite";import { resolve } from "path";
export default defineConfig({ build: { lib: { entry: resolve(__dirname, "src/index.ts"), formats: ["es"], fileName: "index", }, rollupOptions: { external: [/^@aws-sdk/, /^jaypie/, /^@jaypie/], }, outDir: "dist", emptyOutDir: true, },});Package vitest.config.ts
Section titled βPackage vitest.config.tsβimport { defineConfig } from "vitest/config";
export default defineConfig({ test: { environment: "node", setupFiles: ["@jaypie/testkit/testSetup"], },});File Naming
Section titled βFile Namingβ| Pattern | Use Case |
|---|---|
*.ts |
Source files |
*.spec.ts |
Test files (sibling to source) |
*.route.ts |
Express route handlers |
*.router.ts |
Express routers |
*.d.ts |
Type declarations |
Source Structure
Section titled βSource Structureβpackages/api/βββ src/β βββ app.ts # Express appβ βββ handler.ts # Lambda entryβ βββ index.ts # Package exportsβ βββ routers/β β βββ v1.router.tsβ βββ routes/β β βββ health.route.tsβ β βββ health.route.spec.tsβ βββ utils/β βββ db.tsβ βββ db.spec.tsβββ package.jsonβββ tsconfig.jsonβββ vite.config.tsβββ vitest.config.tsCommands
Section titled βCommandsβFrom Root
Section titled βFrom Rootβ# All packagesnpm run build # Build allnpm run test # Test allnpm run lint # Lint allnpm run format # Fix lint issues
# Specific packagenpm run build -w packages/apinpm run test -w packages/apiWorkspace Selection
Section titled βWorkspace Selectionβ# By path (preferred)npm install express -w packages/api
# By namenpm install express -w @project/apiAdding Packages
Section titled βAdding Packagesβ-
Create directory:
Terminal window mkdir -p packages/new-package/src -
Create package.json (from template)
-
Add to vitest.config.ts projects array
-
Install dependencies:
Terminal window npm install -w packages/new-package
NPM Scripts Convention
Section titled βNPM Scripts Conventionβ| Script | Purpose |
|---|---|
build |
Compile TypeScript |
clean |
Remove dist |
dev |
Development mode |
format |
Fix lint issues |
format:package |
Sort package.json |
lint |
Check lint |
test |
Run tests |
typecheck |
Check types |
Related
Section titled βRelatedβ- Express on Lambda - API package setup
- CDK Infrastructure - CDK package setup
- @jaypie/eslint - ESLint configuration
- @jaypie/repokit - Development tools