mirror of https://github.com/buster-so/buster.git
Merge pull request #633 from buster-so/dallin/should-be-able-to-turbo-build-lint-test-unit-without-env-vars
Dallin/should-be-able-to-turbo-build-lint-test-unit-without-env-vars
This commit is contained in:
commit
3e821f5609
|
@ -3,12 +3,6 @@ description:
|
||||||
globs:
|
globs:
|
||||||
alwaysApply: true
|
alwaysApply: true
|
||||||
---
|
---
|
||||||
# CLAUDE.md
|
|
||||||
|
|
||||||
This file provides guidance to Claude Code when working with code in this monorepo.
|
|
||||||
|
|
||||||
**Note**: Many packages and apps have their own CLAUDE.md files with specific implementation details and patterns. Always check for a local CLAUDE.md when working in a specific directory.
|
|
||||||
|
|
||||||
## Monorepo Structure
|
## Monorepo Structure
|
||||||
|
|
||||||
This is a pnpm-based monorepo using Turborepo with the following structure:
|
This is a pnpm-based monorepo using Turborepo with the following structure:
|
||||||
|
@ -54,6 +48,58 @@ When writing code, follow this workflow to ensure code quality:
|
||||||
- Keep business logic separate from infrastructure concerns
|
- Keep business logic separate from infrastructure concerns
|
||||||
- Use proper error handling at each level
|
- Use proper error handling at each level
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
This project uses a centralized environment variable system:
|
||||||
|
|
||||||
|
1. **All environment variables are defined at the root level** in a single `.env` file
|
||||||
|
2. **Turbo passes these variables** to all packages via the `globalEnv` configuration in `turbo.json`
|
||||||
|
3. **Individual packages validate** their required environment variables using the shared `@buster/env-utils` package
|
||||||
|
|
||||||
|
### Setting Up Environment Variables
|
||||||
|
|
||||||
|
1. Copy `.env.example` to `.env` at the project root:
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Fill in the required values in `.env`
|
||||||
|
|
||||||
|
3. All packages will automatically have access to these variables through Turbo
|
||||||
|
|
||||||
|
### Adding New Environment Variables
|
||||||
|
|
||||||
|
When adding new environment variables:
|
||||||
|
|
||||||
|
1. Add the variable to `.env.example` with a descriptive comment
|
||||||
|
2. Add the variable name to the `globalEnv` array in `turbo.json`
|
||||||
|
3. Update the package's `validate-env.js` script to include the new variable
|
||||||
|
4. Update the package's `env.d.ts` file with the TypeScript type definition
|
||||||
|
|
||||||
|
### Migrating Packages to Centralized Env
|
||||||
|
|
||||||
|
To migrate an existing package to use the centralized environment system:
|
||||||
|
|
||||||
|
1. Remove any local `.env` files from the package
|
||||||
|
2. Add `@buster/env-utils` as a dependency:
|
||||||
|
```json
|
||||||
|
"@buster/env-utils": "workspace:*"
|
||||||
|
```
|
||||||
|
3. Update the package's `scripts/validate-env.js` to use the shared utilities:
|
||||||
|
```javascript
|
||||||
|
import { loadRootEnv, validateEnv } from '@buster/env-utils';
|
||||||
|
|
||||||
|
loadRootEnv();
|
||||||
|
|
||||||
|
const requiredEnv = {
|
||||||
|
DATABASE_URL: process.env.DATABASE_URL,
|
||||||
|
// ... other required variables
|
||||||
|
};
|
||||||
|
|
||||||
|
const { hasErrors } = validateEnv(requiredEnv);
|
||||||
|
if (hasErrors) process.exit(1);
|
||||||
|
```
|
||||||
|
|
||||||
### 3. Ensure Type Safety
|
### 3. Ensure Type Safety
|
||||||
```bash
|
```bash
|
||||||
# Build entire monorepo to check types
|
# Build entire monorepo to check types
|
||||||
|
@ -202,18 +248,23 @@ export async function getWorkspaceSettingsHandler(
|
||||||
|
|
||||||
## Database Operations
|
## Database Operations
|
||||||
|
|
||||||
|
### Query Organization
|
||||||
|
- **All database queries must be created as helper functions** in `@packages/database/src/queries/`
|
||||||
|
- **Organize by table** - Each table should have its own subdirectory (e.g., `assets/`, `chats/`, `users/`)
|
||||||
|
- **Type all queries** - Every query function must have properly typed parameters and return types
|
||||||
|
- **Export from index** - Each subdirectory should have an `index.ts` that exports all queries for that table
|
||||||
|
- **Reusable and composable** - Write queries as small, focused functions that can be composed together
|
||||||
|
|
||||||
### Soft Delete and Upsert Practices
|
### Soft Delete and Upsert Practices
|
||||||
- In our database, we never hard delete, we always use soft deletes with the `deleted_at` field
|
- In our database, we never hard delete, we always use soft deletes with the `deleted_at` field
|
||||||
- For update operations, we should almost always perform an upsert unless otherwise specified
|
- For update operations, we should almost always perform an upsert unless otherwise specified
|
||||||
```
|
|
||||||
|
|
||||||
**Test Running Guidelines**:
|
## Test Running Guidelines
|
||||||
- When running tests, use the following Turbo commands:
|
- When running tests, use the following Turbo commands:
|
||||||
- `turbo test:unit` for unit tests
|
- `turbo test:unit` for unit tests
|
||||||
- `turbo test:integration` for integration tests
|
- `turbo test:integration` for integration tests
|
||||||
- `turbo test` for running all tests
|
- `turbo test` for running all tests
|
||||||
# important-instruction-reminders
|
|
||||||
Do what has been asked; nothing more, nothing less.
|
## Pre-Completion Workflow
|
||||||
NEVER create files unless they're absolutely necessary for achieving your goal.
|
- Always run `turbo test:unit, lint, and build:dry-run` before making any pull request or finishing a feature, bugfix, etc. to ensure things make it through CI/CD
|
||||||
ALWAYS prefer editing an existing file to creating a new one.
|
- You can run all these checks simultaneously with `turbo build:dry-run lint test:unit`
|
||||||
NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.
|
|
|
@ -259,10 +259,13 @@ export async function getWorkspaceSettingsHandler(
|
||||||
### Soft Delete and Upsert Practices
|
### Soft Delete and Upsert Practices
|
||||||
- In our database, we never hard delete, we always use soft deletes with the `deleted_at` field
|
- In our database, we never hard delete, we always use soft deletes with the `deleted_at` field
|
||||||
- For update operations, we should almost always perform an upsert unless otherwise specified
|
- For update operations, we should almost always perform an upsert unless otherwise specified
|
||||||
```
|
|
||||||
|
|
||||||
**Test Running Guidelines**:
|
## Test Running Guidelines
|
||||||
- When running tests, use the following Turbo commands:
|
- When running tests, use the following Turbo commands:
|
||||||
- `turbo test:unit` for unit tests
|
- `turbo test:unit` for unit tests
|
||||||
- `turbo test:integration` for integration tests
|
- `turbo test:integration` for integration tests
|
||||||
- `turbo test` for running all tests
|
- `turbo test` for running all tests
|
||||||
|
|
||||||
|
## Pre-Completion Workflow
|
||||||
|
- Always run `turbo test:unit, lint, and build:dry-run` before making any pull request or finishing a feature, bugfix, etc. to ensure things make it through CI/CD
|
||||||
|
- You can run all these checks simultaneously with `turbo build:dry-run lint test:unit`
|
|
@ -7,8 +7,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts && pnpm run typecheck",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || (tsx scripts/validate-env.ts && pnpm run typecheck)",
|
||||||
"build": "tsup",
|
"build": "tsup",
|
||||||
|
"build:dry-run": "tsup",
|
||||||
"dev": "bun --watch src/index.ts",
|
"dev": "bun --watch src/index.ts",
|
||||||
"dev:build": "tsup --watch",
|
"dev:build": "tsup --watch",
|
||||||
"lint": "biome check --write",
|
"lint": "biome check --write",
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "echo 'y' | npx trigger.dev@v4-beta dev",
|
"dev": "echo 'y' | npx trigger.dev@v4-beta dev",
|
||||||
"deploy": "echo 'y' | npx trigger.dev@v4-beta deploy",
|
"deploy": "echo 'y' | npx trigger.dev@v4-beta deploy",
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "echo 'No build step required but we run it to make sure env is loaded' && tsc --noEmit",
|
"build": "echo 'No build step required but we run it to make sure env is loaded' && tsc --noEmit",
|
||||||
|
"build:dry-run": "echo 'No build step required but we run it to make sure env is loaded' && tsc --noEmit",
|
||||||
"lint": "biome check --write",
|
"lint": "biome check --write",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:watch": "vitest watch",
|
"test:watch": "vitest watch",
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ai:dev": "pnpm --filter @buster/ai dev",
|
"ai:dev": "pnpm --filter @buster/ai dev",
|
||||||
"build": "turbo build",
|
"build": "turbo build",
|
||||||
|
"build:dry-run": "SKIP_ENV_CHECK=true turbo run build:dry-run",
|
||||||
"check": "biome check ${1:-.}",
|
"check": "biome check ${1:-.}",
|
||||||
"check:fix": "biome check --write ${1:-.}",
|
"check:fix": "biome check --write ${1:-.}",
|
||||||
"ci:check": "pnpm run check && pnpm run typecheck",
|
"ci:check": "pnpm run check && pnpm run typecheck",
|
||||||
|
|
|
@ -13,8 +13,9 @@
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
||||||
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
||||||
"dev": "tsc --watch",
|
"dev": "tsc --watch",
|
||||||
|
|
|
@ -14,8 +14,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"dev": "tsc --watch",
|
"dev": "tsc --watch",
|
||||||
"dev:mastra": "mastra dev --dir src",
|
"dev:mastra": "mastra dev --dir src",
|
||||||
|
|
|
@ -13,8 +13,9 @@
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
||||||
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
||||||
"lint": "biome check --write",
|
"lint": "biome check --write",
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
||||||
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
||||||
"db:check": "drizzle-kit check",
|
"db:check": "drizzle-kit check",
|
||||||
|
|
|
@ -11,8 +11,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:unit": "vitest run --exclude '**/*.int.test.ts' --exclude '**/*.integration.test.ts' --passWithNoTests",
|
"test:unit": "vitest run --exclude '**/*.int.test.ts' --exclude '**/*.integration.test.ts' --passWithNoTests",
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"dev": "tsc --watch",
|
"dev": "tsc --watch",
|
||||||
"lint": "biome check",
|
"lint": "biome check",
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"dev": "tsc --watch",
|
"dev": "tsc --watch",
|
||||||
"lint": "biome check --write",
|
"lint": "biome check --write",
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
"build:commonjs": "tsc --module commonjs --moduleResolution node",
|
||||||
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
"build:commonjs:watch": "npm run build:commonjs && tsc --module commonjs --moduleResolution node --watch",
|
||||||
"lint": "biome check --write",
|
"lint": "biome check --write",
|
||||||
|
|
|
@ -14,8 +14,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "tsx scripts/validate-env.ts",
|
"prebuild": "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"lint": "biome check --write",
|
"lint": "biome check --write",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
|
|
|
@ -372,12 +372,15 @@ async function createPackageFiles(config: PackageConfig) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
scripts: {
|
scripts: {
|
||||||
prebuild: "tsx scripts/validate-env.ts",
|
prebuild: "[ \"$SKIP_ENV_CHECK\" = \"true\" ] || tsx scripts/validate-env.ts",
|
||||||
build: "tsc",
|
build: "tsc",
|
||||||
|
"build:dry-run": "tsc",
|
||||||
typecheck: "tsc --noEmit",
|
typecheck: "tsc --noEmit",
|
||||||
dev: "tsc --watch",
|
dev: "tsc --watch",
|
||||||
lint: "biome check --write",
|
lint: "biome check --write",
|
||||||
test: "vitest run",
|
test: "vitest run",
|
||||||
|
"test:unit": "vitest run --exclude '**/*.int.test.ts' --exclude '**/*.integration.test.ts' --passWithNoTests",
|
||||||
|
"test:integration": "vitest run **/*.int.test.ts **/*.integration.test.ts",
|
||||||
"test:watch": "vitest watch",
|
"test:watch": "vitest watch",
|
||||||
"test:coverage": "vitest run --coverage",
|
"test:coverage": "vitest run --coverage",
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Skip env validation if SKIP_ENV_CHECK is set
|
||||||
|
if [ "$SKIP_ENV_CHECK" = "true" ]; then
|
||||||
|
echo "Skipping environment validation (dry-run build)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Otherwise run the validation script
|
||||||
|
tsx scripts/validate-env.ts
|
|
@ -7,13 +7,18 @@
|
||||||
"dependsOn": ["^build"],
|
"dependsOn": ["^build"],
|
||||||
"outputs": ["dist/**", ".next/**"]
|
"outputs": ["dist/**", ".next/**"]
|
||||||
},
|
},
|
||||||
|
"build:dry-run": {
|
||||||
|
"dependsOn": ["^build:dry-run"],
|
||||||
|
"outputs": ["dist/**", ".next/**"],
|
||||||
|
"env": ["SKIP_ENV_CHECK"]
|
||||||
|
},
|
||||||
"dev": {
|
"dev": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true,
|
"persistent": true,
|
||||||
"dependsOn": ["@buster/database#dev"]
|
"dependsOn": ["@buster/database#dev"]
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
"dependsOn": ["^build", "^lint"]
|
"dependsOn": ["^lint"]
|
||||||
},
|
},
|
||||||
"typecheck": {
|
"typecheck": {
|
||||||
"dependsOn": ["^build"]
|
"dependsOn": ["^build"]
|
||||||
|
@ -22,7 +27,7 @@
|
||||||
"dependsOn": ["^build"]
|
"dependsOn": ["^build"]
|
||||||
},
|
},
|
||||||
"test:unit": {
|
"test:unit": {
|
||||||
"dependsOn": ["^build"]
|
"dependsOn": ["^test:unit"]
|
||||||
},
|
},
|
||||||
"test:integration": {
|
"test:integration": {
|
||||||
"dependsOn": ["^build"]
|
"dependsOn": ["^build"]
|
||||||
|
|
Loading…
Reference in New Issue