@powerhousedao/ph-cli 6.0.0-dev.29 → 6.0.0-dev.30

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.
@@ -0,0 +1,45 @@
1
+ import { writeCliDocsMarkdownFile } from "@powerhousedao/codegen/file-builders";
2
+ import { accessToken } from "../src/commands/access-token.js";
3
+ import { build, connect, preview, studio } from "../src/commands/connect.js";
4
+ import { generate } from "../src/commands/generate.js";
5
+ import { inspect } from "../src/commands/inspect.js";
6
+ import { install } from "../src/commands/install.js";
7
+ import { list } from "../src/commands/list.js";
8
+ import { login } from "../src/commands/login.js";
9
+ import { migrate } from "../src/commands/migrate.js";
10
+ import { phCli } from "../src/commands/ph-cli.js";
11
+ import { switchboard } from "../src/commands/switchboard.js";
12
+ import { uninstall } from "../src/commands/uninstall.js";
13
+ import { vetra } from "../src/commands/vetra.js";
14
+
15
+ const commands = [
16
+ { name: "generate", command: generate },
17
+ { name: "vetra", command: vetra },
18
+ { name: "connect", command: connect },
19
+ { name: "connect studio", command: studio },
20
+ { name: "connect build", command: build },
21
+ { name: "connect preview", command: preview },
22
+ { name: "access token", command: accessToken },
23
+ { name: "inspect", command: inspect },
24
+ { name: "list", command: list },
25
+ { name: "migrate", command: migrate },
26
+ { name: "switchboard", command: switchboard },
27
+ { name: "login", command: login },
28
+ { name: "install", command: install },
29
+ { name: "uninstall", command: uninstall },
30
+ ];
31
+
32
+ const cliDescription = phCli.description ?? "";
33
+
34
+ async function main() {
35
+ await writeCliDocsMarkdownFile({
36
+ filePath: "COMMANDS.md",
37
+ docsTitle: `Powerhouse CLI Commands (${process.env.WORKSPACE_VERSION || process.env.npm_package_version})`,
38
+ docsIntroduction:
39
+ "This document provides detailed information about the available commands in the Powerhouse CLI.",
40
+ cliDescription,
41
+ entries: commands,
42
+ });
43
+ }
44
+
45
+ await main();
@@ -0,0 +1,84 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ /**
6
+ * Generate COMMANDS.md file from the help texts in help.ts
7
+ */
8
+ async function generateCommandsMd() {
9
+ try {
10
+ // Define paths for ES modules
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+ const rootDir = path.resolve(__dirname, "..");
14
+ const helpFilePath = path.join(rootDir, "src", "help.ts");
15
+ const outputPath = path.join(rootDir, "COMMANDS-LEGACY.md");
16
+
17
+ // Read the help.ts file
18
+ const helpFileContent = fs.readFileSync(helpFilePath, "utf8");
19
+
20
+ // Extract all help text constants using regex
21
+ const helpTextRegex = /export const (\w+)Help = `([\s\S]+?)`;/g;
22
+ const commands: { name: string; content: string }[] = [];
23
+
24
+ let match;
25
+ while ((match = helpTextRegex.exec(helpFileContent)) !== null) {
26
+ const commandName = match[1];
27
+ const helpContent = match[2];
28
+ commands.push({ name: commandName, content: helpContent });
29
+ }
30
+
31
+ // Sort commands alphabetically
32
+ commands.sort((a, b) => a.name.localeCompare(b.name));
33
+
34
+ // Generate the markdown content
35
+ let markdown = "# Powerhouse CLI Commands\n\n";
36
+ markdown +=
37
+ "This document provides detailed information about the available commands in the Powerhouse CLI.\n\n";
38
+ markdown += "## Table of Contents\n\n";
39
+
40
+ // Add table of contents
41
+ commands.forEach((command) => {
42
+ const displayName = formatCommandName(command.name);
43
+ const anchor = displayName.toLowerCase().replace(/\s+/g, "-");
44
+ markdown += `- [${displayName}](#${anchor})\n`;
45
+ });
46
+
47
+ markdown += "\n";
48
+
49
+ // Add command details
50
+ commands.forEach((command) => {
51
+ const displayName = formatCommandName(command.name);
52
+ markdown += `## ${displayName}\n\n`;
53
+ markdown += "```\n";
54
+ markdown += command.content.trim();
55
+ markdown += "\n```\n\n";
56
+ });
57
+
58
+ // Add footer
59
+ markdown += "---\n\n";
60
+ markdown +=
61
+ "*This document was automatically generated from the help text in the codebase.*\n";
62
+
63
+ // Write to COMMANDS.md
64
+ fs.writeFileSync(outputPath, markdown);
65
+
66
+ console.log(`✅ COMMANDS.md has been generated at ${outputPath}`);
67
+ } catch (error) {
68
+ console.error("Failed to generate COMMANDS.md:", error);
69
+ process.exit(1);
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Format command name for display (e.g., "setupGlobals" -> "Setup Globals")
75
+ */
76
+ function formatCommandName(commandName: string): string {
77
+ // Convert camelCase to separate words with spaces
78
+ const name = commandName.replace(/([A-Z])/g, " $1").trim();
79
+ // Capitalize first letter and convert the rest to lowercase
80
+ return name.charAt(0).toUpperCase() + name.slice(1);
81
+ }
82
+
83
+ // Run the script
84
+ generateCommandsMd();
@@ -0,0 +1,22 @@
1
+ import { readFileSync, writeFileSync } from "fs";
2
+ import { join } from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ interface PackageJson {
6
+ version: string;
7
+ }
8
+
9
+ const __dirname = fileURLToPath(new URL(".", import.meta.url));
10
+
11
+ // Read package.json
12
+ const packageJson = JSON.parse(
13
+ readFileSync(join(__dirname, "../package.json"), "utf-8"),
14
+ ) as PackageJson;
15
+
16
+ // Generate version.ts content
17
+ const versionFileContent = `// This file is auto-generated. DO NOT EDIT.
18
+ export const version = "${packageJson.version}";
19
+ `;
20
+
21
+ // Write version.ts
22
+ writeFileSync(join(__dirname, "../src/version.ts"), versionFileContent);
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # =============================================================================
4
+ # Configuration
5
+ # =============================================================================
6
+ PROJECT_NAME=${1:-"global"}
7
+ ACTION=${2:-"status"}
8
+
9
+ # Nginx config file name - remove leading dot to avoid hidden file issues
10
+ # (nginx's include directive with * glob doesn't match hidden files)
11
+ NGINX_CONFIG_NAME="${PROJECT_NAME#.}"
12
+ if [ "$NGINX_CONFIG_NAME" = "" ]; then
13
+ NGINX_CONFIG_NAME="default-ph"
14
+ fi
15
+
16
+ # Get Switchboard port from .env or use default
17
+ if [ -f ".env" ]; then
18
+ SWITCHBOARD_PORT=$(grep "SWITCHBOARD_PORT=" .env | cut -d'=' -f2)
19
+ fi
20
+ SWITCHBOARD_PORT=${SWITCHBOARD_PORT:-4001}
21
+
22
+ # =============================================================================
23
+ # OS Detection and Windows Handling
24
+ # =============================================================================
25
+ if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
26
+ if [ -f "$0.ps1" ]; then
27
+ powershell -ExecutionPolicy Bypass -File "$0.ps1" -PROJECT_NAME "$PROJECT_NAME" -ACTION "$ACTION"
28
+ else
29
+ echo "Error: Windows management script (manage-environment.ps1) not found"
30
+ exit 1
31
+ fi
32
+ else
33
+ # =============================================================================
34
+ # Service Management
35
+ # =============================================================================
36
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
37
+ echo " Managing project: $PROJECT_NAME"
38
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
39
+
40
+ # Function to check if service is properly set up
41
+ check_setup() {
42
+ local project_name=$1
43
+ local error=0
44
+
45
+ # Check if .env file exists
46
+ if [ ! -f ".env" ]; then
47
+ echo "Error: .env file not found in project directory"
48
+ error=1
49
+ fi
50
+
51
+ # Check if Nginx configuration exists
52
+ if [ ! -f "/etc/nginx/sites-available/$NGINX_CONFIG_NAME" ]; then
53
+ echo "Error: Nginx configuration not found at /etc/nginx/sites-available/$NGINX_CONFIG_NAME"
54
+ error=1
55
+ fi
56
+
57
+ # Check if database is configured
58
+ if ! grep -q "DATABASE_URL" ".env"; then
59
+ echo "Error: Database configuration not found in .env file"
60
+ error=1
61
+ fi
62
+
63
+ if [ $error -eq 1 ]; then
64
+ echo "Please run 'ph setup-environment' first to set up the service"
65
+ exit 1
66
+ fi
67
+ }
68
+
69
+ # Function to enable/disable Nginx site
70
+ manage_nginx_site() {
71
+ local action=$1
72
+ local site_path="/etc/nginx/sites-available/$NGINX_CONFIG_NAME"
73
+ local enabled_path="/etc/nginx/sites-enabled/$NGINX_CONFIG_NAME"
74
+
75
+ if [ ! -f "$site_path" ]; then
76
+ echo "Error: Nginx site configuration for $NGINX_CONFIG_NAME not found"
77
+ return 1
78
+ fi
79
+
80
+ case "$action" in
81
+ "enable")
82
+ if [ ! -L "$enabled_path" ]; then
83
+ sudo ln -sf "$site_path" "$enabled_path"
84
+ sudo nginx -t && sudo nginx -s reload
85
+ fi
86
+ ;;
87
+ "disable")
88
+ if [ -L "$enabled_path" ]; then
89
+ sudo rm -f "$enabled_path"
90
+ sudo nginx -t && sudo nginx -s reload
91
+ fi
92
+ ;;
93
+ esac
94
+ }
95
+
96
+ # Function to start services
97
+ start_services() {
98
+ check_setup "$PROJECT_NAME"
99
+ echo "Starting services..."
100
+ # Build Connect
101
+ echo "Building Connect..."
102
+ ph connect build
103
+ sudo rm -rf /var/www/html/${PROJECT_NAME}
104
+ sudo mkdir -p /var/www/html/${PROJECT_NAME}
105
+ sudo cp -r .ph/connect-build/dist/* /var/www/html/${PROJECT_NAME}/
106
+
107
+ # Enable Nginx site
108
+ manage_nginx_site "enable"
109
+
110
+ # Start Switchboard via PM2
111
+ if ! pm2 list | grep -q "switchboard_${PROJECT_NAME}"; then
112
+ cd $PROJECT_NAME
113
+ pm2 start "pnpm switchboard --port $SWITCHBOARD_PORT" --name "switchboard_${PROJECT_NAME}"
114
+ pm2 save
115
+ else
116
+ pm2 start "switchboard_${PROJECT_NAME}"
117
+ fi
118
+ }
119
+
120
+ # Function to stop services
121
+ stop_services() {
122
+ check_setup "$PROJECT_NAME"
123
+ echo "Stopping services..."
124
+ # Stop Switchboard via PM2
125
+ if pm2 list | grep -q "switchboard_${PROJECT_NAME}"; then
126
+ pm2 stop "switchboard_${PROJECT_NAME}"
127
+ fi
128
+
129
+ # Disable Nginx site
130
+ manage_nginx_site "disable"
131
+ }
132
+
133
+ case "$ACTION" in
134
+ "start")
135
+ start_services
136
+ ;;
137
+
138
+ "stop")
139
+ stop_services
140
+ ;;
141
+
142
+ "restart")
143
+ echo "Restarting services..."
144
+ stop_services
145
+ start_services
146
+ ;;
147
+
148
+ "status")
149
+ check_setup "$PROJECT_NAME"
150
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
151
+ echo " Service Status for $PROJECT_NAME"
152
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
153
+
154
+ # Create table header
155
+ printf "%-15s %-10s %-15s %-10s %-10s\n" "Service" "Status" "Memory" "Uptime" "Health"
156
+ echo "────────────────────────────────────────────────────────────────────"
157
+
158
+ # Check Connect status
159
+ connect_status="Disabled"
160
+ connect_health="❌"
161
+ connect_memory="N/A"
162
+ connect_uptime="N/A"
163
+ if [ -L "/etc/nginx/sites-enabled/$NGINX_CONFIG_NAME" ]; then
164
+ connect_status="Enabled"
165
+ # Check if Connect is reachable
166
+ if curl -s -f "http://localhost/$PROJECT_NAME" > /dev/null; then
167
+ connect_health="✅"
168
+ fi
169
+ # Get Nginx memory usage for the site
170
+ nginx_pid=$(pgrep -f "nginx.*$PROJECT_NAME" | head -n 1)
171
+ if [ -n "$nginx_pid" ]; then
172
+ connect_memory=$(ps -o rss= -p "$nginx_pid" 2>/dev/null | awk '{printf "%.1fmb", $1/1024}')
173
+ connect_uptime=$(ps -o etime= -p "$nginx_pid" 2>/dev/null)
174
+ fi
175
+ fi
176
+ printf "%-15s %-10s %-15s %-10s %-10s\n" "Connect" "$connect_status" "$connect_memory" "$connect_uptime" "$connect_health"
177
+
178
+ # Check Switchboard status
179
+ switchboard_info=$(pm2 list | grep "switchboard_${PROJECT_NAME}")
180
+ if [ -n "$switchboard_info" ]; then
181
+ switchboard_status="Enabled"
182
+ switchboard_memory=$(echo "$switchboard_info" | awk '{print $12}')
183
+ switchboard_uptime=$(echo "$switchboard_info" | awk '{print $7}')
184
+ switchboard_health="✅"
185
+ printf "%-15s %-10s %-15s %-10s %-10s\n" "Switchboard" "$switchboard_status" "$switchboard_memory" "$switchboard_uptime" "$switchboard_health"
186
+ else
187
+ printf "%-15s %-10s %-15s %-10s %-10s\n" "Switchboard" "Disabled" "N/A" "N/A" "❌"
188
+ fi
189
+ echo "────────────────────────────────────────────────────────────────────"
190
+ ;;
191
+
192
+ *)
193
+ echo "Usage: $0 [project_name] {start|stop|restart|status}"
194
+ echo "Default project_name: global"
195
+ echo "Default action: status"
196
+ exit 1
197
+ ;;
198
+ esac
199
+ fi
@@ -0,0 +1,423 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # =============================================================================
4
+ # Configuration
5
+ # =============================================================================
6
+ TARGET_TAG=${1:-"latest"}
7
+ PROJECT_NAME=${2:-"global"}
8
+
9
+ # Nginx config file name - remove leading dot to avoid hidden file issues
10
+ # (nginx's include directive with * glob doesn't match hidden files)
11
+ NGINX_CONFIG_NAME="${PROJECT_NAME#.}"
12
+ if [ "$NGINX_CONFIG_NAME" = "" ]; then
13
+ NGINX_CONFIG_NAME="default-ph"
14
+ fi
15
+
16
+ # Function to find an available port
17
+ find_available_port() {
18
+ local port=4001
19
+ while netstat -tuln | grep -q ":$port "; do
20
+ port=$((port + 1))
21
+ done
22
+ echo $port
23
+ }
24
+
25
+ # =============================================================================
26
+ # OS Detection and Windows Handling
27
+ # =============================================================================
28
+ if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
29
+ if [ -f "$0.ps1" ]; then
30
+ powershell -ExecutionPolicy Bypass -File "$0.ps1" -TARGET_TAG "$TARGET_TAG"
31
+ else
32
+ echo "Error: Windows setup script (setup-environment.ps1) not found"
33
+ exit 1
34
+ fi
35
+ else
36
+ # =============================================================================
37
+ # Package Installation
38
+ # =============================================================================
39
+ sudo apt install -y postgresql postgresql-contrib nginx libnginx-mod-http-brotli-static libnginx-mod-http-brotli-filter
40
+ sudo sed -i 's/# gzip_vary/gzip_vary/; s/# gzip_proxied/gzip_proxied/; s/# gzip_comp_level/gzip_comp_level/; s/# gzip_buffers/gzip_buffers/; s/# gzip_http_version/gzip_http_version/; s/# gzip_types/gzip_types/' /etc/nginx/nginx.conf
41
+
42
+ # =============================================================================
43
+ # Interactive Package Installation
44
+ # =============================================================================
45
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
46
+ echo " Package Installation"
47
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
48
+ while true; do
49
+ read -p "Enter package name to install (or press Enter to skip): " package_name
50
+ if [ -z "$package_name" ]; then
51
+ break
52
+ fi
53
+ ph install "$package_name"
54
+ done
55
+
56
+ # =============================================================================
57
+ # Connect Build
58
+ # =============================================================================
59
+ ph connect build
60
+ sudo mkdir -p /var/www/html/$PROJECT_NAME
61
+ sudo cp -r .ph/connect-build/dist/* /var/www/html/$PROJECT_NAME/
62
+
63
+ # =============================================================================
64
+ # Database Configuration
65
+ # =============================================================================
66
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
67
+ echo " Database Configuration"
68
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
69
+ echo "Choose database type:"
70
+ echo "1) Local PostgreSQL database"
71
+ echo "2) Remote PostgreSQL database"
72
+ read -p "Enter your choice (1 or 2): " db_choice
73
+
74
+ if [ "$db_choice" = "1" ]; then
75
+ echo "Setting up local PostgreSQL database..."
76
+
77
+ # Generate database credentials
78
+ DB_PASSWORD="powerhouse"
79
+ DB_USER="powerhouse"
80
+ # Convert to lowercase, replace dots with underscores, replace special chars with underscore, ensure starts with letter
81
+ 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)"
82
+
83
+ # Check if database already exists
84
+ SKIP_DB_CREATE=false
85
+ if sudo -u postgres psql -lqt | cut -d \| -f 1 | grep -qw $DB_NAME; then
86
+ echo "Database $DB_NAME already exists"
87
+ read -p "Do you want to recreate it? (y/n): " recreate_db
88
+ if [ "$recreate_db" = "y" ]; then
89
+ sudo -u postgres psql -c "DROP DATABASE $DB_NAME;"
90
+ else
91
+ echo "Using existing database"
92
+ SKIP_DB_CREATE=true
93
+ fi
94
+ fi
95
+
96
+ # Create user if it doesn't exist
97
+ sudo -u postgres psql << EOF
98
+ DO
99
+ \$do\$
100
+ BEGIN
101
+ IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '$DB_USER') THEN
102
+ CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
103
+ END IF;
104
+ END
105
+ \$do\$;
106
+ EOF
107
+
108
+ # Create database if needed
109
+ if [ "$SKIP_DB_CREATE" = "false" ]; then
110
+ sudo -u postgres psql -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;"
111
+ fi
112
+
113
+ # Grant privileges
114
+ sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;"
115
+
116
+ # Configure PostgreSQL
117
+ sudo sed -i "s/#listen_addresses = 'localhost'/listen_addresses = 'localhost'/" /etc/postgresql/*/main/postgresql.conf
118
+
119
+ # Set DATABASE_URL for local database
120
+ DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost:5432/$DB_NAME"
121
+
122
+ echo "Local database configured successfully!"
123
+ echo "Database URL: $DATABASE_URL"
124
+ echo "Please save these credentials securely!"
125
+ else
126
+ echo "Enter remote PostgreSQL URL (format: postgresql://user:password@host:port/db)"
127
+ echo "Example: postgresql://powerhouse:password@db.example.com:5432/powerhouse"
128
+ read -p "DATABASE_URL: " DATABASE_URL
129
+ fi
130
+
131
+ # Save DATABASE_URL to .env file (update if exists, append if not)
132
+ if grep -q "^DATABASE_URL=" .env 2>/dev/null; then
133
+ sudo sed -i "s|^DATABASE_URL=.*|DATABASE_URL=$DATABASE_URL|" .env
134
+ else
135
+ echo "DATABASE_URL=$DATABASE_URL" | sudo tee -a .env
136
+ fi
137
+
138
+ # =============================================================================
139
+ # SSL Configuration
140
+ # =============================================================================
141
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
142
+ echo " SSL Configuration"
143
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
144
+
145
+ # Find an available port for Switchboard
146
+ SWITCHBOARD_PORT=$(find_available_port)
147
+ echo "Using port $SWITCHBOARD_PORT for Switchboard"
148
+
149
+ # Save Switchboard port to configuration (update if exists, append if not)
150
+ if grep -q "^SWITCHBOARD_PORT=" .env 2>/dev/null; then
151
+ sudo sed -i "s|^SWITCHBOARD_PORT=.*|SWITCHBOARD_PORT=$SWITCHBOARD_PORT|" .env
152
+ else
153
+ echo "SWITCHBOARD_PORT=$SWITCHBOARD_PORT" | sudo tee -a .env
154
+ fi
155
+
156
+ # Add compression settings to nginx.conf if not exists
157
+ if ! grep -q "brotli_comp_level" /etc/nginx/nginx.conf || ! grep -q "gzip_comp_level" /etc/nginx/nginx.conf; then
158
+ echo "Adding compression settings to nginx.conf..."
159
+ # Find the http block in nginx.conf
160
+ if ! grep -q "brotli_comp_level" /etc/nginx/nginx.conf; then
161
+ sudo sed -i '/http {/a \ # Brotli compression\n brotli on;\n brotli_comp_level 6;\n brotli_types text/plain text/css application/javascript application/json image/svg+xml application/xml+rss;\n brotli_static on;' /etc/nginx/nginx.conf
162
+ fi
163
+ if ! grep -q "gzip_comp_level" /etc/nginx/nginx.conf; then
164
+ sudo sed -i '/http {/a \ # Gzip compression\n gzip on;\n gzip_vary on;\n gzip_proxied any;\n gzip_comp_level 6;\n gzip_buffers 16 8k;\n gzip_http_version 1.1;\n gzip_types text/plain text/css application/javascript application/json image/svg+xml application/xml+rss;' /etc/nginx/nginx.conf
165
+ fi
166
+ else
167
+ echo "Compression settings already present in nginx.conf"
168
+ fi
169
+
170
+
171
+
172
+ echo "Choose SSL configuration:"
173
+ echo "1) Let's Encrypt certificates for domains"
174
+ echo "2) Self-signed certificate for machine hostname"
175
+ read -p "Enter your choice (1 or 2): " ssl_choice
176
+
177
+ if [ "$ssl_choice" = "1" ]; then
178
+ # Install certbot
179
+ sudo apt install -y certbot python3-certbot-nginx
180
+
181
+ # =============================================================================
182
+ # Domain Setup
183
+ # =============================================================================
184
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
185
+ echo " Domain Setup"
186
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
187
+ read -p "Enter Connect domain (e.g. connect.google.com): " connect_domain
188
+ read -p "Enter Switchboard domain (e.g. switchboard.google.com): " switchboard_domain
189
+ read -p "Enter admin email for Let's Encrypt notifications: " admin_email
190
+
191
+ echo "Using domains:"
192
+ echo "Connect: $connect_domain"
193
+ echo "Switchboard: $switchboard_domain"
194
+
195
+ # Create initial Nginx configuration for certbot
196
+ echo "Creating initial Nginx configuration..."
197
+ sudo tee /etc/nginx/sites-available/$NGINX_CONFIG_NAME > /dev/null << EOF
198
+ server {
199
+ listen 80;
200
+ server_name $connect_domain $switchboard_domain;
201
+
202
+ location / {
203
+ root /var/www/html/$PROJECT_NAME;
204
+ try_files \$uri \$uri/ /index.html;
205
+ }
206
+
207
+ location /.well-known/acme-challenge/ {
208
+ root /var/www/html;
209
+ }
210
+ }
211
+ EOF
212
+
213
+ # Enable the site
214
+ sudo ln -sf /etc/nginx/sites-available/$NGINX_CONFIG_NAME /etc/nginx/sites-enabled/
215
+ sudo rm -f /etc/nginx/sites-enabled/default
216
+
217
+ # Test Nginx configuration
218
+ sudo nginx -t
219
+
220
+ # Restart Nginx to apply changes
221
+ sudo systemctl restart nginx
222
+
223
+ # Obtain SSL certificates
224
+ echo "Obtaining SSL certificates..."
225
+ sudo certbot --nginx -d $connect_domain --non-interactive --agree-tos --email $admin_email --redirect
226
+ sudo certbot --nginx -d $switchboard_domain --non-interactive --agree-tos --email $admin_email --redirect
227
+
228
+ # Wait for certbot to finish and certificates to be installed
229
+ sleep 5
230
+
231
+ # Check if certificates were installed
232
+ if [ ! -f "/etc/letsencrypt/live/$connect_domain/fullchain.pem" ] || [ ! -f "/etc/letsencrypt/live/$switchboard_domain/fullchain.pem" ]; then
233
+ echo "Error: SSL certificates were not installed properly"
234
+ echo "Please check the certbot logs at /var/log/letsencrypt/letsencrypt.log"
235
+ exit 1
236
+ fi
237
+
238
+ # Update Nginx configuration with proper SSL settings
239
+ echo "Updating Nginx configuration with SSL settings..."
240
+ sudo tee /etc/nginx/sites-available/$NGINX_CONFIG_NAME > /dev/null << EOF
241
+ server {
242
+ listen 80;
243
+ server_name $connect_domain $switchboard_domain;
244
+ return 301 https://\$host\$request_uri;
245
+ }
246
+
247
+ server {
248
+ listen 443 ssl;
249
+ http2 on;
250
+ server_name $connect_domain;
251
+
252
+ ssl_certificate /etc/letsencrypt/live/$connect_domain/fullchain.pem;
253
+ ssl_certificate_key /etc/letsencrypt/live/$connect_domain/privkey.pem;
254
+
255
+ # SSL configuration
256
+ ssl_protocols TLSv1.2 TLSv1.3;
257
+ 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;
258
+ ssl_prefer_server_ciphers off;
259
+ ssl_session_timeout 1d;
260
+ ssl_session_cache shared:SSL:50m;
261
+ ssl_session_tickets off;
262
+ ssl_stapling on;
263
+ ssl_stapling_verify on;
264
+ resolver 8.8.8.8 8.8.4.4 valid=300s;
265
+ resolver_timeout 5s;
266
+
267
+ # Security headers
268
+ add_header Strict-Transport-Security "max-age=63072000" always;
269
+ add_header X-Frame-Options DENY;
270
+ add_header X-Content-Type-Options nosniff;
271
+ add_header X-XSS-Protection "1; mode=block";
272
+
273
+ if (\$http_x_forwarded_proto = "http") {
274
+ return 301 https://\$server_name\$request_uri;
275
+ }
276
+
277
+ location / {
278
+ root /var/www/html/$PROJECT_NAME;
279
+ try_files \$uri \$uri/ /index.html;
280
+ add_header Cache-Control "no-cache";
281
+ add_header X-Forwarded-Proto \$scheme;
282
+ add_header X-Forwarded-Host \$host;
283
+ add_header X-Forwarded-Port \$server_port;
284
+ }
285
+
286
+ location /.well-known/acme-challenge/ {
287
+ root /var/www/html;
288
+ }
289
+ }
290
+
291
+ server {
292
+ listen 443 ssl;
293
+ http2 on;
294
+ server_name $switchboard_domain;
295
+
296
+ ssl_certificate /etc/letsencrypt/live/$switchboard_domain/fullchain.pem;
297
+ ssl_certificate_key /etc/letsencrypt/live/$switchboard_domain/privkey.pem;
298
+
299
+ # SSL configuration
300
+ ssl_protocols TLSv1.2 TLSv1.3;
301
+ 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;
302
+ ssl_prefer_server_ciphers off;
303
+ ssl_session_timeout 1d;
304
+ ssl_session_cache shared:SSL:50m;
305
+ ssl_session_tickets off;
306
+ ssl_stapling on;
307
+ ssl_stapling_verify on;
308
+ resolver 8.8.8.8 8.8.4.4 valid=300s;
309
+ resolver_timeout 5s;
310
+
311
+ # Security headers
312
+ add_header Strict-Transport-Security "max-age=63072000" always;
313
+ add_header X-Frame-Options DENY;
314
+ add_header X-Content-Type-Options nosniff;
315
+ add_header X-XSS-Protection "1; mode=block";
316
+
317
+ location / {
318
+ proxy_pass http://localhost:$SWITCHBOARD_PORT;
319
+ proxy_http_version 1.1;
320
+ proxy_set_header Upgrade \$http_upgrade;
321
+ proxy_set_header Connection 'upgrade';
322
+ proxy_set_header Host \$host;
323
+ proxy_cache_bypass \$http_upgrade;
324
+ proxy_set_header X-Real-IP \$remote_addr;
325
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
326
+ proxy_set_header X-Forwarded-Proto \$scheme;
327
+ }
328
+
329
+ location /.well-known/acme-challenge/ {
330
+ root /var/www/html;
331
+ }
332
+ }
333
+ EOF
334
+
335
+ # Test and reload Nginx configuration
336
+ sudo nginx -t && sudo systemctl reload nginx
337
+
338
+ # Set up automatic renewal
339
+ echo "Setting up automatic certificate renewal..."
340
+ sudo systemctl enable certbot.timer
341
+ sudo systemctl start certbot.timer
342
+
343
+ else
344
+ # Get machine hostname
345
+ hostname=$(hostname)
346
+
347
+ # Generate self-signed certificate
348
+ echo "Generating self-signed certificate for $hostname..."
349
+ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
350
+ -keyout /etc/ssl/private/$hostname.key \
351
+ -out /etc/ssl/certs/$hostname.crt \
352
+ -subj "/CN=$hostname" \
353
+ -addext "subjectAltName = DNS:$hostname"
354
+
355
+ # Create Nginx configuration for self-signed
356
+ echo "Creating Nginx configuration..."
357
+ sudo tee /etc/nginx/sites-available/$NGINX_CONFIG_NAME > /dev/null << EOF
358
+ server {
359
+ listen 80;
360
+ server_name $hostname;
361
+ return 301 https://\$host\$request_uri;
362
+ }
363
+
364
+ server {
365
+ listen 443 ssl;
366
+ http2 on;
367
+ server_name $hostname;
368
+
369
+ ssl_certificate /etc/ssl/certs/$hostname.crt;
370
+ ssl_certificate_key /etc/ssl/private/$hostname.key;
371
+
372
+ # SSL configuration
373
+ ssl_protocols TLSv1.2 TLSv1.3;
374
+ 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;
375
+ ssl_prefer_server_ciphers off;
376
+ ssl_session_timeout 1d;
377
+ ssl_session_cache shared:SSL:50m;
378
+ ssl_session_tickets off;
379
+
380
+ # Security headers
381
+ add_header Strict-Transport-Security "max-age=63072000" always;
382
+ add_header X-Frame-Options DENY;
383
+ add_header X-Content-Type-Options nosniff;
384
+ add_header X-XSS-Protection "1; mode=block";
385
+
386
+ location / {
387
+ root /var/www/html/$PROJECT_NAME;
388
+ try_files \$uri \$uri/ /index.html;
389
+ add_header Cache-Control "no-cache";
390
+ }
391
+
392
+ location /switchboard/ {
393
+ proxy_pass http://localhost:$SWITCHBOARD_PORT/;
394
+ proxy_http_version 1.1;
395
+ proxy_set_header Upgrade \$http_upgrade;
396
+ proxy_set_header Connection 'upgrade';
397
+ proxy_set_header Host \$host;
398
+ proxy_cache_bypass \$http_upgrade;
399
+ proxy_set_header X-Real-IP \$remote_addr;
400
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
401
+ proxy_set_header X-Forwarded-Proto \$scheme;
402
+ }
403
+ }
404
+ EOF
405
+
406
+ # Enable the site
407
+ sudo ln -sf /etc/nginx/sites-available/$NGINX_CONFIG_NAME /etc/nginx/sites-enabled/
408
+ sudo rm -f /etc/nginx/sites-enabled/default
409
+
410
+ # Test and reload Nginx configuration
411
+ sudo nginx -t && sudo systemctl reload nginx
412
+ fi
413
+
414
+ # =============================================================================
415
+ # Database Schema Setup
416
+ # =============================================================================
417
+ pnpm prisma db push --schema node_modules/document-drive/dist/prisma/schema.prisma --skip-generate
418
+
419
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
420
+ echo " Environment setup complete!"
421
+ echo " Use 'ph service start' to start services"
422
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
423
+ 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 --skip-generate
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
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env bash
2
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
3
+ \. ~/.nvm/nvm.sh
4
+ export NVM_DIR="$HOME/.nvm"
5
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
6
+ [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
7
+ nvm --version
8
+ nvm install 22
9
+ curl -fsSL https://get.pnpm.io/install.sh | sh -
10
+ export PNPM_HOME="/home/$USER/.local/share/pnpm"
11
+ export PATH="$PNPM_HOME:$PATH"
12
+ pnpm install -g ph-cmd
13
+ echo ""
14
+ echo " 🎉 Setup Complete! 🎉"
15
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
16
+ echo " To complete installation:"
17
+ echo " 1. Restart your terminal"
18
+ echo " OR"
19
+ echo " Run: source ~/.bashrc"
20
+ echo ""
21
+ echo " 2. Start using Powerhouse by typing:"
22
+ echo " ph"
23
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
24
+ echo ""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/ph-cli",
3
- "version": "6.0.0-dev.29",
3
+ "version": "6.0.0-dev.30",
4
4
  "description": "",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
@@ -37,8 +37,8 @@
37
37
  "copyfiles": "^2.4.1",
38
38
  "nodemon": "^3.1.9",
39
39
  "vitest": "^3.2.4",
40
- "document-drive": "6.0.0-dev.29",
41
- "document-model": "6.0.0-dev.29"
40
+ "document-drive": "6.0.0-dev.30",
41
+ "document-model": "6.0.0-dev.30"
42
42
  },
43
43
  "dependencies": {
44
44
  "chalk": "^5.6.2",
@@ -53,13 +53,13 @@
53
53
  "ts-morph": "^26.0.0",
54
54
  "vite": "^7.2.6",
55
55
  "write-package": "^7.2.0",
56
- "@powerhousedao/builder-tools": "6.0.0-dev.29",
57
- "@powerhousedao/codegen": "6.0.0-dev.29",
58
- "@powerhousedao/common": "6.0.0-dev.29",
59
- "@powerhousedao/config": "6.0.0-dev.29",
60
- "@powerhousedao/reactor": "6.0.0-dev.29",
61
- "@powerhousedao/switchboard": "6.0.0-dev.29",
62
- "@renown/sdk": "6.0.0-dev.29"
56
+ "@powerhousedao/builder-tools": "6.0.0-dev.30",
57
+ "@powerhousedao/codegen": "6.0.0-dev.30",
58
+ "@powerhousedao/common": "6.0.0-dev.30",
59
+ "@powerhousedao/reactor": "6.0.0-dev.30",
60
+ "@powerhousedao/config": "6.0.0-dev.30",
61
+ "@powerhousedao/switchboard": "6.0.0-dev.30",
62
+ "@renown/sdk": "6.0.0-dev.30"
63
63
  },
64
64
  "scripts": {
65
65
  "tsc": "tsc",