@powerhousedao/ph-cli 0.41.2 → 2.5.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +122 -18
  2. package/dist/package.json +13 -1
  3. package/dist/scripts/generate-commands-md.ts +84 -0
  4. package/dist/scripts/generate-version.ts +22 -0
  5. package/dist/scripts/manage-environment +190 -0
  6. package/dist/scripts/setup-environment +380 -0
  7. package/dist/scripts/setup-environment.ps1 +313 -0
  8. package/dist/scripts/setup.sh +24 -0
  9. package/dist/src/cli.js +17 -2
  10. package/dist/src/cli.js.map +1 -1
  11. package/dist/src/commands/connect.d.ts +1 -1
  12. package/dist/src/commands/connect.d.ts.map +1 -1
  13. package/dist/src/commands/connect.js +39 -9
  14. package/dist/src/commands/connect.js.map +1 -1
  15. package/dist/src/commands/index.d.ts.map +1 -1
  16. package/dist/src/commands/index.js +3 -1
  17. package/dist/src/commands/index.js.map +1 -1
  18. package/dist/src/commands/install.d.ts +2 -1
  19. package/dist/src/commands/install.d.ts.map +1 -1
  20. package/dist/src/commands/install.js +39 -10
  21. package/dist/src/commands/install.js.map +1 -1
  22. package/dist/src/commands/list.d.ts.map +1 -1
  23. package/dist/src/commands/list.js +2 -2
  24. package/dist/src/commands/list.js.map +1 -1
  25. package/dist/src/commands/reactor.d.ts +9 -0
  26. package/dist/src/commands/reactor.d.ts.map +1 -0
  27. package/dist/src/commands/reactor.js +39 -0
  28. package/dist/src/commands/reactor.js.map +1 -0
  29. package/dist/src/commands/service.d.ts +1 -1
  30. package/dist/src/commands/service.d.ts.map +1 -1
  31. package/dist/src/commands/service.js +48 -126
  32. package/dist/src/commands/service.js.map +1 -1
  33. package/dist/src/commands/switchboard.d.ts +5 -5
  34. package/dist/src/commands/switchboard.d.ts.map +1 -1
  35. package/dist/src/commands/switchboard.js +18 -12
  36. package/dist/src/commands/switchboard.js.map +1 -1
  37. package/dist/src/commands/uninstall.d.ts.map +1 -1
  38. package/dist/src/commands/uninstall.js +10 -1
  39. package/dist/src/commands/uninstall.js.map +1 -1
  40. package/dist/src/help.d.ts +15 -3
  41. package/dist/src/help.d.ts.map +1 -1
  42. package/dist/src/help.js +80 -15
  43. package/dist/src/help.js.map +1 -1
  44. package/dist/src/services/connect.js +1 -1
  45. package/dist/src/services/connect.js.map +1 -1
  46. package/dist/src/services/dev.d.ts.map +1 -1
  47. package/dist/src/services/dev.js +2 -2
  48. package/dist/src/services/dev.js.map +1 -1
  49. package/dist/src/services/generate.js +1 -1
  50. package/dist/src/services/generate.js.map +1 -1
  51. package/dist/src/services/inspect.d.ts.map +1 -1
  52. package/dist/src/services/inspect.js +3 -2
  53. package/dist/src/services/inspect.js.map +1 -1
  54. package/dist/src/services/reactor.d.ts +32 -0
  55. package/dist/src/services/reactor.d.ts.map +1 -0
  56. package/dist/src/services/reactor.js +66 -0
  57. package/dist/src/services/reactor.js.map +1 -0
  58. package/dist/src/services/switchboard.d.ts +2 -31
  59. package/dist/src/services/switchboard.d.ts.map +1 -1
  60. package/dist/src/services/switchboard.js +24 -58
  61. package/dist/src/services/switchboard.js.map +1 -1
  62. package/dist/src/utils.d.ts +11 -3
  63. package/dist/src/utils.d.ts.map +1 -1
  64. package/dist/src/utils.js +8 -7
  65. package/dist/src/utils.js.map +1 -1
  66. package/dist/src/version.d.ts +1 -1
  67. package/dist/src/version.d.ts.map +1 -1
  68. package/dist/src/version.js +1 -1
  69. package/dist/src/version.js.map +1 -1
  70. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  71. package/dist/vitest.config.d.ts +3 -0
  72. package/dist/vitest.config.d.ts.map +1 -0
  73. package/dist/vitest.config.js +7 -0
  74. package/dist/vitest.config.js.map +1 -0
  75. package/package.json +20 -8
  76. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,380 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # =============================================================================
4
+ # Configuration
5
+ # =============================================================================
6
+ TARGET_TAG=${1:-"latest"}
7
+ PROJECT_NAME=${2:-"global"}
8
+
9
+ # =============================================================================
10
+ # OS Detection and Windows Handling
11
+ # =============================================================================
12
+ if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
13
+ if [ -f "$0.ps1" ]; then
14
+ powershell -ExecutionPolicy Bypass -File "$0.ps1" -TARGET_TAG "$TARGET_TAG"
15
+ else
16
+ echo "Error: Windows setup script (setup-environment.ps1) not found"
17
+ exit 1
18
+ fi
19
+ else
20
+ # =============================================================================
21
+ # Package Installation
22
+ # =============================================================================
23
+ sudo apt install -y postgresql postgresql-contrib nginx
24
+
25
+ # =============================================================================
26
+ # Interactive Package Installation
27
+ # =============================================================================
28
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
29
+ echo " Package Installation"
30
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
31
+ while true; do
32
+ read -p "Enter package name to install (or press Enter to skip): " package_name
33
+ if [ -z "$package_name" ]; then
34
+ break
35
+ fi
36
+ ph install "$package_name"
37
+ done
38
+
39
+ # =============================================================================
40
+ # Connect Build
41
+ # =============================================================================
42
+ ph connect build
43
+ cp -r .ph/connect-build/dist /var/www/html/$PROJECT_NAME
44
+
45
+ # =============================================================================
46
+ # Database Configuration
47
+ # =============================================================================
48
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
49
+ echo " Database Configuration"
50
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
51
+ echo "Choose database type:"
52
+ echo "1) Local PostgreSQL database"
53
+ echo "2) Remote PostgreSQL database"
54
+ read -p "Enter your choice (1 or 2): " db_choice
55
+
56
+ if [ "$db_choice" = "1" ]; then
57
+ echo "Setting up local PostgreSQL database..."
58
+
59
+ # Generate database credentials
60
+ DB_PASSWORD="powerhouse"
61
+ DB_USER="powerhouse"
62
+ # Convert to lowercase, replace dots with underscores, replace special chars with underscore, ensure starts with letter
63
+ DB_NAME="powerhouse_$(echo "${PROJECT_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/\./_/g' | sed 's/[^a-z0-9]/_/g' | sed 's/^[^a-z]/p_/' | cut -c1-63)"
64
+
65
+ # Check if database already exists
66
+ if sudo -u postgres psql -lqt | cut -d \| -f 1 | grep -qw $DB_NAME; then
67
+ echo "Database $DB_NAME already exists"
68
+ read -p "Do you want to recreate it? (y/n): " recreate_db
69
+ if [ "$recreate_db" = "y" ]; then
70
+ sudo -u postgres psql -c "DROP DATABASE $DB_NAME;"
71
+ else
72
+ echo "Using existing database"
73
+ fi
74
+ fi
75
+
76
+ # Create database and user if they don't exist
77
+ sudo -u postgres psql << EOF
78
+ DO
79
+ \$do\$
80
+ BEGIN
81
+ IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '$DB_USER') THEN
82
+ CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
83
+ END IF;
84
+ END
85
+ \$do\$;
86
+
87
+ CREATE DATABASE $DB_NAME OWNER $DB_USER;
88
+ GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
89
+ EOF
90
+
91
+ # Configure PostgreSQL
92
+ sudo sed -i "s/#listen_addresses = 'localhost'/listen_addresses = 'localhost'/" /etc/postgresql/*/main/postgresql.conf
93
+
94
+ # Set DATABASE_URL for local database
95
+ DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost:5432/$DB_NAME"
96
+
97
+ echo "Local database configured successfully!"
98
+ echo "Database URL: $DATABASE_URL"
99
+ echo "Please save these credentials securely!"
100
+ else
101
+ echo "Enter remote PostgreSQL URL (format: postgresql://user:password@host:port/db)"
102
+ echo "Example: postgresql://powerhouse:password@db.example.com:5432/powerhouse"
103
+ read -p "DATABASE_URL: " DATABASE_URL
104
+ fi
105
+
106
+ # Save DATABASE_URL to .env file
107
+ echo "DATABASE_URL=$DATABASE_URL" | sudo tee -a .env
108
+
109
+ # =============================================================================
110
+ # SSL Configuration
111
+ # =============================================================================
112
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
113
+ echo " SSL Configuration"
114
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
115
+ echo "Choose SSL configuration:"
116
+ echo "1) Let's Encrypt certificates for domains"
117
+ echo "2) Self-signed certificate for machine hostname"
118
+ read -p "Enter your choice (1 or 2): " ssl_choice
119
+
120
+ if [ "$ssl_choice" = "1" ]; then
121
+ # Install certbot
122
+ sudo apt install -y certbot python3-certbot-nginx
123
+
124
+ # =============================================================================
125
+ # Domain Setup
126
+ # =============================================================================
127
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
128
+ echo " Domain Setup"
129
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
130
+ read -p "Enter Connect domain (e.g. connect.google.com): " connect_domain
131
+ read -p "Enter Switchboard domain (e.g. switchboard.google.com): " switchboard_domain
132
+
133
+ echo "Using domains:"
134
+ echo "Connect: $connect_domain"
135
+ echo "Switchboard: $switchboard_domain"
136
+
137
+ # Generate temporary SSL certificates
138
+ echo "Generating temporary SSL certificates..."
139
+ sudo mkdir -p /etc/nginx/ssl
140
+ sudo openssl req -x509 -nodes -days 1 -newkey rsa:2048 \
141
+ -keyout /etc/nginx/ssl/temp.key \
142
+ -out /etc/nginx/ssl/temp.crt \
143
+ -subj "/CN=$connect_domain" \
144
+ -addext "subjectAltName = DNS:$connect_domain,DNS:$switchboard_domain"
145
+
146
+ # Check if Nginx configuration already exists
147
+ if [ -f "/etc/nginx/sites-available/$PROJECT_NAME" ]; then
148
+ echo "Nginx configuration for $PROJECT_NAME already exists"
149
+ read -p "Do you want to overwrite it? (y/n): " overwrite_nginx
150
+ if [ "$overwrite_nginx" != "y" ]; then
151
+ echo "Keeping existing Nginx configuration"
152
+ else
153
+ # Create Nginx configuration for domains
154
+ echo "Creating Nginx configuration..."
155
+ sudo tee /etc/nginx/sites-available/$PROJECT_NAME > /dev/null << EOF
156
+ # Security headers
157
+ add_header Strict-Transport-Security "max-age=63072000" always;
158
+ add_header X-Frame-Options DENY;
159
+ add_header X-Content-Type-Options nosniff;
160
+ add_header X-XSS-Protection "1; mode=block";
161
+
162
+ server {
163
+ listen 80;
164
+ server_name $connect_domain $switchboard_domain;
165
+ return 301 https://\$host\$request_uri;
166
+ }
167
+
168
+ server {
169
+ listen 443 ssl http2;
170
+ server_name $connect_domain;
171
+
172
+ ssl_certificate /etc/nginx/ssl/temp.crt;
173
+ ssl_certificate_key /etc/nginx/ssl/temp.key;
174
+
175
+ # SSL configuration
176
+ ssl_protocols TLSv1.2 TLSv1.3;
177
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
178
+ ssl_prefer_server_ciphers off;
179
+ ssl_session_timeout 1d;
180
+ ssl_session_cache shared:SSL:50m;
181
+ ssl_session_tickets off;
182
+ ssl_stapling on;
183
+ ssl_stapling_verify on;
184
+
185
+ if (\$http_x_forwarded_proto = "http") {
186
+ return 301 https://\$server_name\$request_uri;
187
+ }
188
+
189
+ location / {
190
+ root $PWD/.ph/connect-build/dist;
191
+ try_files \$uri \$uri/ /index.html;
192
+ add_header Cache-Control "no-cache";
193
+ add_header X-Forwarded-Proto \$scheme;
194
+ add_header X-Forwarded-Host \$host;
195
+ add_header X-Forwarded-Port \$server_port;
196
+ }
197
+ }
198
+
199
+ server {
200
+ listen 443 ssl http2;
201
+ server_name $switchboard_domain;
202
+
203
+ ssl_certificate /etc/nginx/ssl/temp.crt;
204
+ ssl_certificate_key /etc/nginx/ssl/temp.key;
205
+
206
+ location / {
207
+ proxy_pass http://localhost:4001;
208
+ proxy_http_version 1.1;
209
+ proxy_set_header Upgrade \$http_upgrade;
210
+ proxy_set_header Connection 'upgrade';
211
+ proxy_set_header Host \$host;
212
+ proxy_cache_bypass \$http_upgrade;
213
+ proxy_set_header X-Real-IP \$remote_addr;
214
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
215
+ proxy_set_header X-Forwarded-Proto \$scheme;
216
+ }
217
+ }
218
+ EOF
219
+ fi
220
+ else
221
+ # Create Nginx configuration for domains
222
+ echo "Creating Nginx configuration..."
223
+ sudo tee /etc/nginx/sites-available/$PROJECT_NAME > /dev/null << EOF
224
+ # Security headers
225
+ add_header Strict-Transport-Security "max-age=63072000" always;
226
+ add_header X-Frame-Options DENY;
227
+ add_header X-Content-Type-Options nosniff;
228
+ add_header X-XSS-Protection "1; mode=block";
229
+
230
+ server {
231
+ listen 80;
232
+ server_name $connect_domain $switchboard_domain;
233
+ return 301 https://\$host\$request_uri;
234
+ }
235
+
236
+ server {
237
+ listen 443 ssl http2;
238
+ server_name $connect_domain;
239
+
240
+ ssl_certificate /etc/nginx/ssl/temp.crt;
241
+ ssl_certificate_key /etc/nginx/ssl/temp.key;
242
+
243
+ # SSL configuration
244
+ ssl_protocols TLSv1.2 TLSv1.3;
245
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
246
+ ssl_prefer_server_ciphers off;
247
+ ssl_session_timeout 1d;
248
+ ssl_session_cache shared:SSL:50m;
249
+ ssl_session_tickets off;
250
+ ssl_stapling on;
251
+ ssl_stapling_verify on;
252
+
253
+ if (\$http_x_forwarded_proto = "http") {
254
+ return 301 https://\$server_name\$request_uri;
255
+ }
256
+
257
+ location / {
258
+ root /var/www/html/$PROJECT_NAME;
259
+ try_files \$uri \$uri/ /index.html;
260
+ add_header Cache-Control "no-cache";
261
+ add_header X-Forwarded-Proto \$scheme;
262
+ add_header X-Forwarded-Host \$host;
263
+ add_header X-Forwarded-Port \$server_port;
264
+ }
265
+ }
266
+
267
+ server {
268
+ listen 443 ssl http2;
269
+ server_name $switchboard_domain;
270
+
271
+ ssl_certificate /etc/nginx/ssl/temp.crt;
272
+ ssl_certificate_key /etc/nginx/ssl/temp.key;
273
+
274
+ location / {
275
+ proxy_pass http://localhost:4001;
276
+ proxy_http_version 1.1;
277
+ proxy_set_header Upgrade \$http_upgrade;
278
+ proxy_set_header Connection 'upgrade';
279
+ proxy_set_header Host \$host;
280
+ proxy_cache_bypass \$http_upgrade;
281
+ proxy_set_header X-Real-IP \$remote_addr;
282
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
283
+ proxy_set_header X-Forwarded-Proto \$scheme;
284
+ }
285
+ }
286
+ EOF
287
+ fi
288
+
289
+ # Enable the site
290
+ sudo ln -sf /etc/nginx/sites-available/$PROJECT_NAME /etc/nginx/sites-enabled/
291
+ sudo rm -f /etc/nginx/sites-enabled/default
292
+
293
+ # Test Nginx configuration
294
+ sudo nginx -t
295
+
296
+ # Obtain SSL certificates
297
+ echo "Obtaining SSL certificates..."
298
+ sudo certbot --nginx -d $connect_domain -d $switchboard_domain --non-interactive --agree-tos --email admin@$connect_domain
299
+
300
+ # Remove temporary certificates
301
+ sudo rm -f /etc/nginx/ssl/temp.*
302
+
303
+ else
304
+ # Get machine hostname
305
+ hostname=$(hostname)
306
+
307
+ # Generate self-signed certificate
308
+ echo "Generating self-signed certificate for $hostname..."
309
+ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
310
+ -keyout /etc/ssl/private/$hostname.key \
311
+ -out /etc/ssl/certs/$hostname.crt \
312
+ -subj "/CN=$hostname" \
313
+ -addext "subjectAltName = DNS:$hostname"
314
+
315
+ # Create Nginx configuration for self-signed
316
+ echo "Creating Nginx configuration..."
317
+ sudo tee /etc/nginx/sites-available/$PROJECT_NAME > /dev/null << EOF
318
+ # Security headers
319
+ add_header Strict-Transport-Security "max-age=63072000" always;
320
+ add_header X-Frame-Options DENY;
321
+ add_header X-Content-Type-Options nosniff;
322
+ add_header X-XSS-Protection "1; mode=block";
323
+
324
+ server {
325
+ listen 80;
326
+ server_name $hostname;
327
+ return 301 https://\$host\$request_uri;
328
+ }
329
+
330
+ server {
331
+ listen 443 ssl http2;
332
+ server_name $hostname;
333
+
334
+ ssl_certificate /etc/ssl/certs/$hostname.crt;
335
+ ssl_certificate_key /etc/ssl/private/$hostname.key;
336
+
337
+ location /connect {
338
+ proxy_pass http://localhost:3000;
339
+ proxy_http_version 1.1;
340
+ proxy_set_header Upgrade \$http_upgrade;
341
+ proxy_set_header Connection 'upgrade';
342
+ proxy_set_header Host \$host;
343
+ proxy_cache_bypass \$http_upgrade;
344
+ proxy_set_header X-Real-IP \$remote_addr;
345
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
346
+ proxy_set_header X-Forwarded-Proto \$scheme;
347
+ }
348
+
349
+ location /switchboard {
350
+ proxy_pass http://localhost:4001;
351
+ proxy_http_version 1.1;
352
+ proxy_set_header Upgrade \$http_upgrade;
353
+ proxy_set_header Connection 'upgrade';
354
+ proxy_set_header Host \$host;
355
+ proxy_cache_bypass \$http_upgrade;
356
+ proxy_set_header X-Real-IP \$remote_addr;
357
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
358
+ proxy_set_header X-Forwarded-Proto \$scheme;
359
+ }
360
+ }
361
+ EOF
362
+
363
+ # Enable the site
364
+ sudo ln -sf /etc/nginx/sites-available/$PROJECT_NAME /etc/nginx/sites-enabled/
365
+ sudo rm -f /etc/nginx/sites-enabled/default
366
+
367
+ # Test Nginx configuration
368
+ sudo nginx -t
369
+ fi
370
+
371
+ # =============================================================================
372
+ # Database Schema Setup
373
+ # =============================================================================
374
+ pnpm prisma db push --schema node_modules/document-drive/dist/prisma/schema.prisma
375
+
376
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
377
+ echo " Environment setup complete!"
378
+ echo " Use 'ph service start' to start services"
379
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
380
+ fi
@@ -0,0 +1,313 @@
1
+ # PowerShell script for setting up Powerhouse environment on Windows
2
+ param(
3
+ [string]$TARGET_TAG = "latest"
4
+ )
5
+
6
+ # Function to check if running as administrator
7
+ function Test-Administrator {
8
+ $user = [Security.Principal.WindowsIdentity]::GetCurrent()
9
+ $principal = New-Object Security.Principal.WindowsPrincipal $user
10
+ $principal.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
11
+ }
12
+
13
+ # Check if running as administrator
14
+ if (-not (Test-Administrator)) {
15
+ Write-Host "Please run this script as Administrator" -ForegroundColor Red
16
+ exit 1
17
+ }
18
+
19
+ # Install required packages using winget
20
+ Write-Host "Installing required packages..."
21
+ winget install -e --id PostgreSQL.PostgreSQL
22
+ winget install -e --id NGINX.NGINX
23
+
24
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
25
+ Write-Host " Setting up global project"
26
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
27
+
28
+ # Create installation directory if it doesn't exist
29
+ $installPath = "C:\www"
30
+ if (-not (Test-Path $installPath)) {
31
+ New-Item -ItemType Directory -Path $installPath
32
+ }
33
+ Set-Location $installPath
34
+
35
+ # Initialize Powerhouse project
36
+ ph init powerhouse --$TARGET_TAG
37
+ Set-Location powerhouse
38
+
39
+ # Interactive package installation loop
40
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
41
+ Write-Host " Package Installation"
42
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
43
+ while ($true) {
44
+ $package_name = Read-Host "Enter package name to install (or press Enter to skip)"
45
+ if ([string]::IsNullOrEmpty($package_name)) {
46
+ break
47
+ }
48
+ ph install $package_name
49
+ }
50
+
51
+ # Build Connect
52
+ ph connect build
53
+
54
+ # Database Configuration
55
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
56
+ Write-Host " Database Configuration"
57
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
58
+ Write-Host "Choose database type:"
59
+ Write-Host "1) Local PostgreSQL database"
60
+ Write-Host "2) Remote PostgreSQL database"
61
+ $db_choice = Read-Host "Enter your choice (1 or 2)"
62
+
63
+ if ($db_choice -eq "1") {
64
+ Write-Host "Setting up local PostgreSQL database..."
65
+
66
+ # Generate database credentials
67
+ $DB_PASSWORD = "powerhouse"
68
+ $DB_USER = "powerhouse"
69
+ $DB_NAME = "powerhouse"
70
+
71
+ # Create database and user using psql
72
+ $env:PGPASSWORD = "postgres" # Default PostgreSQL password
73
+ psql -U postgres -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';"
74
+ psql -U postgres -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;"
75
+ psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;"
76
+
77
+ # Set DATABASE_URL for local database
78
+ $DATABASE_URL = "postgresql://$DB_USER`:$DB_PASSWORD@localhost:5432/$DB_NAME"
79
+
80
+ Write-Host "Local database configured successfully!"
81
+ Write-Host "Database URL: $DATABASE_URL"
82
+ Write-Host "Please save these credentials securely!"
83
+ } else {
84
+ Write-Host "Enter remote PostgreSQL URL (format: postgresql://user:password@host:port/db)"
85
+ Write-Host "Example: postgresql://powerhouse:password@db.example.com:5432/powerhouse"
86
+ $DATABASE_URL = Read-Host "DATABASE_URL"
87
+ }
88
+
89
+ # Save DATABASE_URL to .env file
90
+ Add-Content -Path "$installPath\powerhouse\.env" -Value "DATABASE_URL=$DATABASE_URL"
91
+
92
+ # SSL Configuration choice
93
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
94
+ Write-Host " SSL Configuration"
95
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
96
+ Write-Host "Choose SSL configuration:"
97
+ Write-Host "1) Let's Encrypt certificates for domains"
98
+ Write-Host "2) Self-signed certificate for machine hostname"
99
+ $ssl_choice = Read-Host "Enter your choice (1 or 2)"
100
+
101
+ if ($ssl_choice -eq "1") {
102
+ # Install certbot for Let's Encrypt
103
+ winget install -e --id Certbot.Certbot
104
+
105
+ # Domain setup
106
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
107
+ Write-Host " Domain Setup"
108
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
109
+ $base_domain = Read-Host "Enter base domain (e.g. powerhouse.xyz)"
110
+ $connect_subdomain = Read-Host "Enter subdomain for Connect service (default: connect)"
111
+ $switchboard_subdomain = Read-Host "Enter subdomain for Switchboard service (default: switchboard)"
112
+
113
+ # Set default subdomains if not provided
114
+ if ([string]::IsNullOrEmpty($connect_subdomain)) { $connect_subdomain = "connect" }
115
+ if ([string]::IsNullOrEmpty($switchboard_subdomain)) { $switchboard_subdomain = "switchboard" }
116
+
117
+ # Construct full domains
118
+ $connect_domain = "$connect_subdomain.$base_domain"
119
+ $switchboard_domain = "$switchboard_subdomain.$base_domain"
120
+
121
+ Write-Host "Using domains:"
122
+ Write-Host "Connect: $connect_domain"
123
+ Write-Host "Switchboard: $switchboard_domain"
124
+
125
+ # Generate temporary SSL certificates
126
+ Write-Host "Generating temporary SSL certificates..."
127
+ $sslPath = "C:\nginx\ssl"
128
+ if (-not (Test-Path $sslPath)) {
129
+ New-Item -ItemType Directory -Path $sslPath
130
+ }
131
+
132
+ # Create Nginx configuration for domains
133
+ $nginxConfig = @"
134
+ # Security headers
135
+ add_header Strict-Transport-Security "max-age=63072000" always;
136
+ add_header X-Frame-Options DENY;
137
+ add_header X-Content-Type-Options nosniff;
138
+ add_header X-XSS-Protection "1; mode=block";
139
+
140
+ server {
141
+ listen 80;
142
+ server_name $connect_domain $switchboard_domain;
143
+ return 301 https://`$host`$request_uri;
144
+ }
145
+
146
+ server {
147
+ listen 443 ssl http2;
148
+ server_name $connect_domain;
149
+
150
+ ssl_certificate $sslPath\temp.crt;
151
+ ssl_certificate_key $sslPath\temp.key;
152
+
153
+ # SSL configuration
154
+ ssl_protocols TLSv1.2 TLSv1.3;
155
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
156
+ ssl_prefer_server_ciphers off;
157
+ ssl_session_timeout 1d;
158
+ ssl_session_cache shared:SSL:50m;
159
+ ssl_session_tickets off;
160
+ ssl_stapling on;
161
+ ssl_stapling_verify on;
162
+
163
+ if (`$http_x_forwarded_proto = "http") {
164
+ return 301 https://`$server_name`$request_uri;
165
+ }
166
+
167
+ location / {
168
+ root C:/www/powerhouse/.ph/connect-build/dist;
169
+ try_files `$uri `$uri/ /index.html;
170
+ add_header Cache-Control "no-cache";
171
+ add_header X-Forwarded-Proto `$scheme;
172
+ add_header X-Forwarded-Host `$host;
173
+ add_header X-Forwarded-Port `$server_port;
174
+ }
175
+ }
176
+
177
+ server {
178
+ listen 443 ssl http2;
179
+ server_name $switchboard_domain;
180
+
181
+ ssl_certificate $sslPath\temp.crt;
182
+ ssl_certificate_key $sslPath\temp.key;
183
+
184
+ location / {
185
+ proxy_pass http://localhost:4001;
186
+ proxy_http_version 1.1;
187
+ proxy_set_header Upgrade `$http_upgrade;
188
+ proxy_set_header Connection 'upgrade';
189
+ proxy_set_header Host `$host;
190
+ proxy_cache_bypass `$http_upgrade;
191
+ proxy_set_header X-Real-IP `$remote_addr;
192
+ proxy_set_header X-Forwarded-For `$proxy_add_x_forwarded_for;
193
+ proxy_set_header X-Forwarded-Proto `$scheme;
194
+ }
195
+ }
196
+ "@
197
+
198
+ # Save Nginx configuration
199
+ $nginxConfig | Out-File -FilePath "C:\nginx\conf\sites-available\powerhouse.conf" -Encoding UTF8
200
+
201
+ # Create symbolic link to enable the site
202
+ if (-not (Test-Path "C:\nginx\conf\sites-enabled")) {
203
+ New-Item -ItemType Directory -Path "C:\nginx\conf\sites-enabled"
204
+ }
205
+ New-Item -ItemType SymbolicLink -Path "C:\nginx\conf\sites-enabled\powerhouse.conf" -Target "C:\nginx\conf\sites-available\powerhouse.conf" -Force
206
+
207
+ # Test Nginx configuration
208
+ nginx -t
209
+
210
+ # Restart Nginx
211
+ Stop-Service nginx
212
+ Start-Service nginx
213
+
214
+ # Obtain SSL certificates
215
+ Write-Host "Obtaining SSL certificates..."
216
+ certbot --nginx -d $connect_domain -d $switchboard_domain --non-interactive --agree-tos --email "admin@$base_domain"
217
+
218
+ } else {
219
+ # Get machine hostname
220
+ $hostname = [System.Net.Dns]::GetHostName()
221
+
222
+ # Generate self-signed certificate
223
+ Write-Host "Generating self-signed certificate for $hostname..."
224
+ $sslPath = "C:\nginx\ssl"
225
+ if (-not (Test-Path $sslPath)) {
226
+ New-Item -ItemType Directory -Path $sslPath
227
+ }
228
+
229
+ # Create Nginx configuration for self-signed
230
+ $nginxConfig = @"
231
+ # Security headers
232
+ add_header Strict-Transport-Security "max-age=63072000" always;
233
+ add_header X-Frame-Options DENY;
234
+ add_header X-Content-Type-Options nosniff;
235
+ add_header X-XSS-Protection "1; mode=block";
236
+
237
+ server {
238
+ listen 80;
239
+ server_name $hostname;
240
+ return 301 https://`$host`$request_uri;
241
+ }
242
+
243
+ server {
244
+ listen 443 ssl http2;
245
+ server_name $hostname;
246
+
247
+ ssl_certificate $sslPath\$hostname.crt;
248
+ ssl_certificate_key $sslPath\$hostname.key;
249
+
250
+ location /connect {
251
+ proxy_pass http://localhost:3000;
252
+ proxy_http_version 1.1;
253
+ proxy_set_header Upgrade `$http_upgrade;
254
+ proxy_set_header Connection 'upgrade';
255
+ proxy_set_header Host `$host;
256
+ proxy_cache_bypass `$http_upgrade;
257
+ proxy_set_header X-Real-IP `$remote_addr;
258
+ proxy_set_header X-Forwarded-For `$proxy_add_x_forwarded_for;
259
+ proxy_set_header X-Forwarded-Proto `$scheme;
260
+ }
261
+
262
+ location /switchboard {
263
+ proxy_pass http://localhost:4001;
264
+ proxy_http_version 1.1;
265
+ proxy_set_header Upgrade `$http_upgrade;
266
+ proxy_set_header Connection 'upgrade';
267
+ proxy_set_header Host `$host;
268
+ proxy_cache_bypass `$http_upgrade;
269
+ proxy_set_header X-Real-IP `$remote_addr;
270
+ proxy_set_header X-Forwarded-For `$proxy_add_x_forwarded_for;
271
+ proxy_set_header X-Forwarded-Proto `$scheme;
272
+ }
273
+ }
274
+ "@
275
+
276
+ # Save Nginx configuration
277
+ $nginxConfig | Out-File -FilePath "C:\nginx\conf\sites-available\powerhouse.conf" -Encoding UTF8
278
+
279
+ # Create symbolic link to enable the site
280
+ if (-not (Test-Path "C:\nginx\conf\sites-enabled")) {
281
+ New-Item -ItemType Directory -Path "C:\nginx\conf\sites-enabled"
282
+ }
283
+ New-Item -ItemType SymbolicLink -Path "C:\nginx\conf\sites-enabled\powerhouse.conf" -Target "C:\nginx\conf\sites-available\powerhouse.conf" -Force
284
+
285
+ # Test Nginx configuration
286
+ nginx -t
287
+
288
+ # Restart Nginx
289
+ Stop-Service nginx
290
+ Start-Service nginx
291
+ }
292
+
293
+ # Install PM2 globally if not already installed
294
+ if (-not (Get-Command pm2 -ErrorAction SilentlyContinue)) {
295
+ pnpm install -g pm2
296
+ }
297
+
298
+ # Run database migrations
299
+ pnpm prisma db push --schema node_modules/document-drive/dist/prisma/schema.prisma
300
+
301
+ # Start services with PM2
302
+ Write-Host "Starting services with PM2..."
303
+ if ($ssl_choice -eq "2") {
304
+ # Self-signed certificate - use base paths
305
+ pm2 start pnpm switchboard --name "switchboard" -- --base-path /switchboard
306
+ } else {
307
+ # Let's Encrypt - no base paths needed
308
+ pm2 start "pnpm switchboard" --name "switchboard"
309
+ }
310
+
311
+ # Save PM2 process list and setup startup script
312
+ pm2 save
313
+ pm2 startup