mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-07 07:55:16 +02:00
Feat/add developer docs for windows (#213)
* docs: add windows commands for developer setup * feat: add windows scripts * fix(ui): make dev script cross-platform with cross-env * feat(scripts): enhance migration scripts for Alembic environment setup and add virtual environment activation
This commit is contained in:
parent
e7adbc7bad
commit
66b085dde2
10 changed files with 443 additions and 13 deletions
|
|
@ -35,6 +35,12 @@ dograh/
|
|||
./scripts/stop_services.sh
|
||||
```
|
||||
|
||||
On Windows (PowerShell):
|
||||
```powershell
|
||||
.\scripts\start_services_dev.ps1
|
||||
.\scripts\stop_services.ps1
|
||||
```
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
- `api/.env` - Backend environment variables
|
||||
|
|
|
|||
|
|
@ -8,10 +8,14 @@ If the below steps do not work out for you, it would be great if you can open an
|
|||
|
||||
### System Requirements
|
||||
- git to clone the forked repository
|
||||
- Node.js 24 to run the UI (we recommend using [NVM](https://github.com/nvm-sh/nvm) to manage your node versions locally)
|
||||
- Node.js 24 to run the UI (we recommend using [NVM](https://github.com/nvm-sh/nvm) on macOS/Linux or [NVM for Windows](https://github.com/coreybutler/nvm-windows) on Windows to manage your node versions locally)
|
||||
- Python 3.13 to run the backend
|
||||
- Docker to run the database and redis cache locally
|
||||
|
||||
<Note>
|
||||
All commands below are shown for **macOS / Linux**. Expand the **Windows** tab for the PowerShell equivalent where it differs.
|
||||
</Note>
|
||||
|
||||
### Steps
|
||||
1. Fork the Dograh repository by going to https://github.com/dograh-hq/dograh
|
||||
2. Clone the forked repository on your machine
|
||||
|
|
@ -20,10 +24,16 @@ git clone https://github.com/<GITHUB_HANDLE>/dograh
|
|||
cd dograh
|
||||
```
|
||||
3. Create a python virtual environment
|
||||
```
|
||||
<CodeGroup>
|
||||
```bash macOS/Linux
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
```
|
||||
```powershell Windows
|
||||
python -m venv venv
|
||||
.\venv\Scripts\Activate.ps1
|
||||
```
|
||||
</CodeGroup>
|
||||
4. Install the requirements
|
||||
```
|
||||
pip install -r api/requirements.txt
|
||||
|
|
@ -50,25 +60,51 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS
|
|||
a57e3e92b02c minio/minio "/usr/bin/docker-ent…" 18 seconds ago Up 18 seconds (healthy) 127.0.0.1:9000-9001->9000-9001/tcp dograh-minio-1
|
||||
```
|
||||
8. Setup environment variables
|
||||
``
|
||||
<CodeGroup>
|
||||
```bash macOS/Linux
|
||||
cp api/.env.example api/.env && cp ui/.env.example ui/.env
|
||||
``
|
||||
9. Setup pipecat git submodule
|
||||
```
|
||||
```powershell Windows
|
||||
Copy-Item api/.env.example api/.env
|
||||
Copy-Item ui/.env.example ui/.env
|
||||
```
|
||||
</CodeGroup>
|
||||
9. Setup pipecat git submodule
|
||||
<CodeGroup>
|
||||
```bash macOS/Linux
|
||||
bash scripts/setup_pipecat.sh
|
||||
```
|
||||
10. Start backend services
|
||||
```powershell Windows
|
||||
.\scripts\setup_pipecat.ps1
|
||||
```
|
||||
</CodeGroup>
|
||||
10. Start backend services
|
||||
<CodeGroup>
|
||||
```bash macOS/Linux
|
||||
bash scripts/start_services_dev.sh
|
||||
```
|
||||
```powershell Windows
|
||||
.\scripts\start_services_dev.ps1
|
||||
```
|
||||
</CodeGroup>
|
||||
Verify that your backend server is running
|
||||
<CodeGroup>
|
||||
```bash macOS/Linux
|
||||
curl -X GET localhost:8000/api/v1/health
|
||||
```
|
||||
curl -X GET localhost:8000/api/v1/health
|
||||
```powershell Windows
|
||||
curl.exe http://localhost:8000/api/v1/health
|
||||
```
|
||||
</CodeGroup>
|
||||
You would be able to see the logs in logs/ directory.
|
||||
```
|
||||
<CodeGroup>
|
||||
```bash macOS/Linux
|
||||
tail -f logs/latest/*.log
|
||||
```
|
||||
```powershell Windows
|
||||
Get-Content logs/latest/*.log -Wait
|
||||
```
|
||||
</CodeGroup>
|
||||
11. Start the UI
|
||||
```
|
||||
cd ui && npm run dev
|
||||
|
|
|
|||
|
|
@ -9,11 +9,17 @@ description: "Common issues and solutions for running Dograh AI"
|
|||
|
||||
### When a port is already in use:
|
||||
##### Check what's using the port first and then kill the process (may require sudo on Linux)
|
||||
```bash
|
||||
<CodeGroup>
|
||||
```bash macOS/Linux
|
||||
lsof -i :3010
|
||||
|
||||
kill -9 $(lsof -t -i :3010)
|
||||
```
|
||||
```powershell Windows
|
||||
netstat -ano | findstr :3010
|
||||
# Find the PID in the last column, then:
|
||||
Stop-Process -Id <PID> -Force
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### When Docker containers are using the ports (with auto-restart enabled):
|
||||
|
||||
|
|
|
|||
58
scripts/makemigrate.ps1
Normal file
58
scripts/makemigrate.ps1
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env pwsh
|
||||
# Create a new Alembic migration with autogenerate (Windows)
|
||||
|
||||
Param(
|
||||
[string]$MigrationName,
|
||||
[switch]$DryRun
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$BaseDir = Split-Path -Parent $ScriptDir
|
||||
Set-Location $BaseDir
|
||||
|
||||
# Ensure repository root is importable for Alembic env/module resolution.
|
||||
if ($env:PYTHONPATH) {
|
||||
$env:PYTHONPATH = "$BaseDir;$($env:PYTHONPATH)"
|
||||
} else {
|
||||
$env:PYTHONPATH = $BaseDir
|
||||
}
|
||||
|
||||
$EnvFile = Join-Path $BaseDir 'api/.env'
|
||||
|
||||
# Load environment variables
|
||||
if (Test-Path $EnvFile) {
|
||||
Get-Content $EnvFile | ForEach-Object {
|
||||
$line = $_.Trim()
|
||||
if ($line -and -not $line.StartsWith('#')) {
|
||||
$parts = $line -split '=', 2
|
||||
if ($parts.Count -eq 2) {
|
||||
[Environment]::SetEnvironmentVariable($parts[0].Trim(), $parts[1].Trim().Trim('"'), 'Process')
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host "Error: Environment file $EnvFile not found." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Prompt for migration name when not provided via parameter
|
||||
if (-not $MigrationName) {
|
||||
$MigrationName = Read-Host "Enter the migration name (minimum 5 characters)"
|
||||
}
|
||||
|
||||
if (-not $MigrationName -or $MigrationName.Length -lt 5) {
|
||||
Write-Host "Error: Migration name must be at least 5 characters long." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Generate the Alembic revision
|
||||
$cmd = "alembic -c api/alembic.ini revision --autogenerate -m `"$MigrationName`""
|
||||
|
||||
if ($DryRun) {
|
||||
Write-Host "Dry run: $cmd"
|
||||
exit 0
|
||||
}
|
||||
|
||||
alembic -c api/alembic.ini revision --autogenerate -m $MigrationName
|
||||
36
scripts/migrate.ps1
Normal file
36
scripts/migrate.ps1
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env pwsh
|
||||
# Run Alembic database migrations (Windows)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$BaseDir = Split-Path -Parent $ScriptDir
|
||||
Set-Location $BaseDir
|
||||
|
||||
# Ensure repository root is importable for Alembic env/module resolution.
|
||||
if ($env:PYTHONPATH) {
|
||||
$env:PYTHONPATH = "$BaseDir;$($env:PYTHONPATH)"
|
||||
} else {
|
||||
$env:PYTHONPATH = $BaseDir
|
||||
}
|
||||
|
||||
$EnvFile = Join-Path $BaseDir 'api/.env'
|
||||
|
||||
# Load environment variables
|
||||
if (Test-Path $EnvFile) {
|
||||
Get-Content $EnvFile | ForEach-Object {
|
||||
$line = $_.Trim()
|
||||
if ($line -and -not $line.StartsWith('#')) {
|
||||
$parts = $line -split '=', 2
|
||||
if ($parts.Count -eq 2) {
|
||||
[Environment]::SetEnvironmentVariable($parts[0].Trim(), $parts[1].Trim().Trim('"'), 'Process')
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host "Error: Environment file $EnvFile not found." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Run migrations
|
||||
alembic -c api/alembic.ini upgrade head
|
||||
24
scripts/setup_pipecat.ps1
Normal file
24
scripts/setup_pipecat.ps1
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env pwsh
|
||||
# Setup script for using pipecat as a git submodule (Windows)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$BaseDir = Split-Path -Parent $ScriptDir
|
||||
Set-Location $BaseDir
|
||||
|
||||
Write-Host "Setting up pipecat as a git submodule..."
|
||||
|
||||
# Initialize and update submodules
|
||||
Write-Host "Initializing git submodules..."
|
||||
git submodule update --init --recursive
|
||||
|
||||
# Install pipecat in editable mode with all extras
|
||||
Write-Host "Installing pipecat dependencies..."
|
||||
pip install -e './pipecat[cartesia,deepgram,openai,elevenlabs,groq,google,azure,sarvam,soundfile,silero,webrtc,speechmatics,openrouter,camb]'
|
||||
|
||||
# Install other requirements
|
||||
Write-Host "Installing dograh API requirements..."
|
||||
pip install -r api/requirements.txt
|
||||
|
||||
Write-Host "Setup complete! Pipecat is now available as a git submodule."
|
||||
151
scripts/start_services_dev.ps1
Normal file
151
scripts/start_services_dev.ps1
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/env pwsh
|
||||
# Start Dograh services in development mode (Windows)
|
||||
# Usage: .\scripts\start_services_dev.ps1 [-ArqWorkers 2] [-NoMigrations] [-IncludeTelephonyWorkers]
|
||||
#
|
||||
# Note: Telephony workers (ari_manager, campaign_orchestrator) are disabled by
|
||||
# default on Windows because they use Unix signal handlers not supported by the
|
||||
# Windows asyncio event loop.
|
||||
|
||||
Param(
|
||||
[int]$ArqWorkers = 1,
|
||||
[switch]$NoMigrations,
|
||||
[switch]$IncludeTelephonyWorkers
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
###############################################################################
|
||||
### CONFIGURATION
|
||||
###############################################################################
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$BaseDir = Split-Path -Parent $ScriptDir
|
||||
Set-Location $BaseDir
|
||||
|
||||
$EnvFile = Join-Path $BaseDir 'api/.env'
|
||||
$RunDir = Join-Path $BaseDir 'run'
|
||||
$LogsRoot = Join-Path $BaseDir 'logs'
|
||||
$LatestDir = Join-Path $LogsRoot 'latest'
|
||||
$VenvPath = Join-Path $BaseDir 'venv'
|
||||
|
||||
Write-Host "Starting Dograh Services (DEV MODE) in BASE_DIR: $BaseDir"
|
||||
Write-Host "Auto-reload enabled for api/ directory changes"
|
||||
|
||||
###############################################################################
|
||||
### 1) Load environment variables
|
||||
###############################################################################
|
||||
|
||||
if (Test-Path $EnvFile) {
|
||||
Get-Content $EnvFile | ForEach-Object {
|
||||
$line = $_.Trim()
|
||||
if ($line -and -not $line.StartsWith('#')) {
|
||||
$parts = $line -split '=', 2
|
||||
if ($parts.Count -eq 2) {
|
||||
[Environment]::SetEnvironmentVariable($parts[0].Trim(), $parts[1].Trim().Trim('"'), 'Process')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $env:UVICORN_BASE_PORT) { $env:UVICORN_BASE_PORT = '8000' }
|
||||
|
||||
###############################################################################
|
||||
### 2) Define services
|
||||
###############################################################################
|
||||
|
||||
$serviceSpecs = @()
|
||||
|
||||
if ($IncludeTelephonyWorkers) {
|
||||
$serviceSpecs += @{ Name = 'ari_manager'; Cmd = "python -m api.services.telephony.ari_manager" }
|
||||
$serviceSpecs += @{ Name = 'campaign_orchestrator'; Cmd = "python -m api.services.campaign.campaign_orchestrator" }
|
||||
}
|
||||
|
||||
$serviceSpecs += @{ Name = 'uvicorn'; Cmd = "uvicorn api.app:app --host 0.0.0.0 --port $($env:UVICORN_BASE_PORT) --reload --reload-dir api" }
|
||||
|
||||
for ($i = 1; $i -le $ArqWorkers; $i++) {
|
||||
$serviceSpecs += @{ Name = "arq$i"; Cmd = "python -m arq api.tasks.arq.WorkerSettings --custom-log-dict api.tasks.arq.LOG_CONFIG" }
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
### 3) Activate virtual environment
|
||||
###############################################################################
|
||||
|
||||
$VenvActivateScript = Join-Path $VenvPath 'Scripts/Activate.ps1'
|
||||
|
||||
if (Test-Path $VenvActivateScript) {
|
||||
. $VenvActivateScript
|
||||
Write-Host "Virtual environment activated: $VenvPath"
|
||||
} else {
|
||||
Write-Host "Warning: Virtual environment not found at $VenvPath"
|
||||
Write-Host "Continuing without virtual environment activation..."
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
### 4) Stop old services
|
||||
###############################################################################
|
||||
|
||||
New-Item -ItemType Directory -Path $RunDir -Force | Out-Null
|
||||
|
||||
foreach ($spec in $serviceSpecs) {
|
||||
$pidFile = Join-Path $RunDir "$($spec.Name).pid"
|
||||
if (Test-Path $pidFile) {
|
||||
$oldPid = (Get-Content $pidFile -Raw).Trim()
|
||||
if ($oldPid) {
|
||||
$prev = $ErrorActionPreference; $ErrorActionPreference = 'SilentlyContinue'
|
||||
& taskkill /PID $oldPid /T /F 2>&1 | Out-Null
|
||||
$ErrorActionPreference = $prev
|
||||
}
|
||||
Remove-Item $pidFile -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
### 5) Run migrations
|
||||
###############################################################################
|
||||
|
||||
if (-not $NoMigrations) {
|
||||
alembic -c (Join-Path $BaseDir 'api/alembic.ini') upgrade head
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
### 6) Prepare logs
|
||||
###############################################################################
|
||||
|
||||
New-Item -ItemType Directory -Path $LatestDir -Force | Out-Null
|
||||
Get-ChildItem $LatestDir -Filter '*.log' -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue
|
||||
|
||||
###############################################################################
|
||||
### 7) Start services
|
||||
###############################################################################
|
||||
|
||||
foreach ($spec in $serviceSpecs) {
|
||||
$name = $spec.Name
|
||||
$logPath = Join-Path $LatestDir "$name.log"
|
||||
$pidFile = Join-Path $RunDir "$name.pid"
|
||||
|
||||
Write-Host "-> Starting $name"
|
||||
|
||||
$wrapped = "cd /d `"$BaseDir`" && $($spec.Cmd) >> `"$logPath`" 2>&1"
|
||||
$proc = Start-Process cmd.exe -ArgumentList '/c', $wrapped -PassThru -WindowStyle Hidden
|
||||
|
||||
Set-Content -Path $pidFile -Value $proc.Id
|
||||
Write-Host " PID $($proc.Id) -> $logPath"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
### 8) Summary
|
||||
###############################################################################
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "------------------------------------------------------"
|
||||
Write-Host "Mode: DEVELOPMENT (auto-reload enabled)"
|
||||
Write-Host ""
|
||||
foreach ($spec in $serviceSpecs) {
|
||||
$procId = (Get-Content (Join-Path $RunDir "$($spec.Name).pid") -Raw).Trim()
|
||||
Write-Host " $($spec.Name) (PID $procId) -> logs/latest/$($spec.Name).log"
|
||||
}
|
||||
Write-Host ""
|
||||
Write-Host "Health: curl.exe http://localhost:$($env:UVICORN_BASE_PORT)/api/v1/health"
|
||||
Write-Host "Logs: Get-Content logs/latest/*.log -Wait"
|
||||
Write-Host "Stop: .\scripts\stop_services.ps1"
|
||||
Write-Host "------------------------------------------------------"
|
||||
92
scripts/stop_services.ps1
Normal file
92
scripts/stop_services.ps1
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/env pwsh
|
||||
# Stop Dograh services started by start_services_dev.ps1 (Windows)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
###############################################################################
|
||||
### CONFIGURATION
|
||||
###############################################################################
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$BaseDir = Split-Path -Parent $ScriptDir
|
||||
$RunDir = Join-Path $BaseDir 'run'
|
||||
|
||||
Set-Location $BaseDir
|
||||
Write-Host "Stopping Dograh Services in BASE_DIR: $BaseDir"
|
||||
|
||||
###############################################################################
|
||||
### HELPER
|
||||
###############################################################################
|
||||
|
||||
function Stop-ProcessTree([int]$ProcessId) {
|
||||
# taskkill /T kills the entire process tree. Temporarily relax error
|
||||
# preference so that a "process not found" message on stderr does not
|
||||
# terminate the script.
|
||||
$prev = $ErrorActionPreference
|
||||
try {
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
& taskkill /PID $ProcessId /T /F 2>&1 | Out-Null
|
||||
} finally {
|
||||
$ErrorActionPreference = $prev
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
### STOP SERVICES
|
||||
###############################################################################
|
||||
|
||||
if (-not (Test-Path $RunDir)) {
|
||||
Write-Host "No run directory found at $RunDir"
|
||||
Write-Host "No services appear to be running."
|
||||
exit 0
|
||||
}
|
||||
|
||||
$pidFiles = Get-ChildItem $RunDir -Filter '*.pid' -ErrorAction SilentlyContinue
|
||||
if (-not $pidFiles) {
|
||||
Write-Host "No PID files found in $RunDir"
|
||||
Write-Host "No services appear to be running."
|
||||
exit 0
|
||||
}
|
||||
|
||||
$stoppedCount = 0
|
||||
$failedCount = 0
|
||||
|
||||
foreach ($pidFile in $pidFiles) {
|
||||
$name = $pidFile.BaseName
|
||||
$oldPid = (Get-Content $pidFile.FullName -Raw).Trim()
|
||||
|
||||
$proc = Get-Process -Id ([int]$oldPid) -ErrorAction SilentlyContinue
|
||||
if ($proc) {
|
||||
Write-Host "Stopping $name (PID $oldPid)..."
|
||||
Stop-ProcessTree ([int]$oldPid)
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
$still = Get-Process -Id ([int]$oldPid) -ErrorAction SilentlyContinue
|
||||
if ($still) {
|
||||
Write-Host " Warning: $name did not exit cleanly"
|
||||
$failedCount++
|
||||
} else {
|
||||
Write-Host " Stopped $name"
|
||||
$stoppedCount++
|
||||
}
|
||||
} else {
|
||||
# The tracked cmd.exe may have exited but child processes may still run.
|
||||
# Best-effort cleanup via taskkill tree kill.
|
||||
Stop-ProcessTree ([int]$oldPid)
|
||||
Write-Host "Service $name (PID $oldPid) is not running"
|
||||
}
|
||||
|
||||
Remove-Item $pidFile.FullName -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
### SUMMARY
|
||||
###############################################################################
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "------------------------------------------------------"
|
||||
Write-Host "Stopped $stoppedCount service(s)"
|
||||
if ($failedCount -gt 0) {
|
||||
Write-Host "Failed to stop $failedCount service(s)"
|
||||
}
|
||||
Write-Host "------------------------------------------------------"
|
||||
24
ui/package-lock.json
generated
24
ui/package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "ui",
|
||||
"version": "1.16.0",
|
||||
"version": "1.19.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ui",
|
||||
"version": "1.16.0",
|
||||
"version": "1.19.2",
|
||||
"dependencies": {
|
||||
"@dagrejs/dagre": "^1.1.4",
|
||||
"@hey-api/client-fetch": "^0.10.0",
|
||||
|
|
@ -62,6 +62,7 @@
|
|||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@types/source-map-support": "^0.5.10",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "^15.3.3",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
|
|
@ -12900,6 +12901,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"cross-env": "src/bin/cross-env.js",
|
||||
"cross-env-shell": "src/bin/cross-env-shell.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.14",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.20.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "NODE_OPTIONS='--enable-source-maps' next dev --turbopack",
|
||||
"dev": "cross-env NODE_OPTIONS=--enable-source-maps next dev --turbopack",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
|
|
@ -60,6 +60,7 @@
|
|||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3",
|
||||
"@hey-api/openapi-ts": "^0.66.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"@tailwindcss/postcss": "^4",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue