Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,27 @@ Or run `npx echo-start my-app` to choose interactively.

# Development

Fill out `packages/app/control/.env` and `packages/app/server/.env`. Then...
Prerequisites:

- `pnpm i`
- `pnpm dev`
- Node.js 18 or newer
- pnpm 10.11.0 or newer
- Docker with Docker Compose

From a fresh clone:

```bash
pnpm i
pnpm dev
```

`pnpm dev` runs the local setup step automatically. It creates
`packages/app/control/.env` from `.env.example` when needed, generates a local
`AUTH_SECRET`, sets the local PostgreSQL `DATABASE_URL`, starts the Docker
PostgreSQL container, applies Prisma migrations, and starts the control app plus
router server.

If `pnpm` is not available yet, install the pinned version first:

```bash
npm install -g pnpm@10.11.0
```
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"private": true,
"packageManager": "pnpm@10.11.0",
"scripts": {
"predev": "pnpm run local-setup",
"dev": "turbo run dev --filter=echo-control --filter=echo-server",
"local-setup": "turbo run local-setup --filter=echo-control",
"build": "turbo run build --env-mode=loose",
Expand Down
81 changes: 63 additions & 18 deletions packages/app/control/scripts/setup.sh
Original file line number Diff line number Diff line change
@@ -1,20 +1,65 @@
#!/bin/bash

# Check if .env file exists and if AUTH_SECRET is already set
if [ -f .env ] && grep -q "^AUTH_SECRET=" .env; then
echo "AUTH_SECRET already exists in .env file. Skipping generation."
else
echo "Generating AUTH_SECRET..."
AUTH_SECRET=$(node -e "console.log('AUTH_SECRET=' + require('crypto').randomBytes(32).toString('base64'))")
echo $AUTH_SECRET
echo $AUTH_SECRET >> .env
fi

# Check if DATABASE_URL is already set
if [ -f .env ] && grep -q "^DATABASE_URL=" .env; then
echo "DATABASE_URL already exists in .env file. Skipping."
else
echo "DATABASE_URL='postgresql://echo_user:echo_password@localhost:5469/echo_control_v2?schema=public'" >> .env
fi

echo "Setup complete! You can now run 'pnpm dev' to start the development server."
set -euo pipefail

ENV_FILE=".env"
DATABASE_URL_VALUE='"postgresql://echo_user:echo_password@localhost:5469/echo_control_v2?schema=public"'

ensure_env_file() {
if [ -f "$ENV_FILE" ]; then
return
fi

if [ -f ".env.example" ]; then
cp ".env.example" "$ENV_FILE"
echo "Created $ENV_FILE from .env.example."
else
touch "$ENV_FILE"
echo "Created empty $ENV_FILE."
fi
}

env_value() {
local key="$1"
grep -E "^${key}=" "$ENV_FILE" | tail -n 1 | cut -d= -f2- | tr -d "\"'"
}

set_env_value() {
local key="$1"
local value="$2"
local current

current="$(env_value "$key" || true)"
if [ -n "$current" ]; then
echo "$key already exists in $ENV_FILE. Skipping."
return
fi

if grep -qE "^${key}=" "$ENV_FILE"; then
local temp_file
temp_file="$(mktemp)"
awk -v key="$key" -v replacement="${key}=${value}" '
BEGIN { replaced = 0 }
$0 ~ "^" key "=" && replaced == 0 {
print replacement
replaced = 1
next
}
{ print }
' "$ENV_FILE" > "$temp_file"
mv "$temp_file" "$ENV_FILE"
else
printf "%s=%s\n" "$key" "$value" >> "$ENV_FILE"
fi

echo "Set $key in $ENV_FILE."
}

ensure_env_file

AUTH_SECRET_VALUE="\"$(node -e "process.stdout.write(require('crypto').randomBytes(32).toString('base64'))")\""

set_env_value "AUTH_SECRET" "$AUTH_SECRET_VALUE"
set_env_value "DATABASE_URL" "$DATABASE_URL_VALUE"

echo "Setup complete. You can now run 'pnpm dev' to start the development server."
2 changes: 1 addition & 1 deletion packages/sdk/examples/next-402-chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"build": "next build --turbopack",
"start": "next start",
"lint": "biome check --write",
"postinstall": "npm dedupe || true"
"postinstall": "node -e \"if (!(process.env.npm_config_user_agent || '').includes('pnpm')) require('child_process').execSync('npm dedupe', { stdio: 'inherit' })\" || true"
},
"dependencies": {
"@ai-sdk/openai": "2.0.16",
Expand Down