@powerhousedao/ph-cli 0.40.85-dev.0 → 0.40.85-dev.1

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.
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/ph-cli",
3
- "version": "0.40.85-dev.0",
3
+ "version": "0.40.85-dev.1",
4
4
  "description": "",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
@@ -17,6 +17,8 @@
17
17
  "generate-commands-md": "tsx scripts/generate-commands-md.ts",
18
18
  "generate-version": "tsx scripts/generate-version.ts",
19
19
  "prebuild": "npm run clean && npm run generate-commands-md && npm run generate-version",
20
+ "postbuild": "npm run copy-scripts",
21
+ "copy-scripts": "copyfiles scripts/* dist/",
20
22
  "build": "tsc --build",
21
23
  "dev": "concurrently -P 'pnpm -w run build:tsc --watch' 'nodemon --watch \"../..\" -e ts,tsx,js,json dist/src/cli.js -- {@}' --",
22
24
  "prepublishOnly": "npm run build",
@@ -32,6 +34,7 @@
32
34
  "devDependencies": {
33
35
  "@types/node": "^22.15.17",
34
36
  "concurrently": "^9.1.2",
37
+ "copyfiles": "^2.4.1",
35
38
  "nodemon": "^3.1.9",
36
39
  "vitest": "^3.1.2"
37
40
  },
@@ -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.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,7 @@
1
+ #!/bin/bash
2
+ OUTPUT=$(pm2 startup | tail -n 1)
3
+ eval $OUTPUT
4
+ ps aux | grep pm2 | grep -v grep | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1
5
+ sudo systemctl daemon-reload
6
+ sudo systemctl enable pm2-$USER
7
+ sudo systemctl start pm2-$USER
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+ sudo systemctl stop pm2-$USER
3
+ sudo systemctl disable pm2-$USER
4
+ OUTPUT=$(pm2 unstartup | tail -n 1)
5
+ eval $OUTPUT
6
+ sudo systemctl daemon-reload
@@ -0,0 +1,318 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # =============================================================================
4
+ # Configuration
5
+ # =============================================================================
6
+ TARGET_TAG=${1:-"latest"}
7
+
8
+ # =============================================================================
9
+ # OS Detection and Windows Handling
10
+ # =============================================================================
11
+ if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
12
+ if [ -f "$0.ps1" ]; then
13
+ powershell -ExecutionPolicy Bypass -File "$0.ps1" -TARGET_TAG "$TARGET_TAG"
14
+ else
15
+ echo "Error: Windows setup script (setup-environment.ps1) not found"
16
+ exit 1
17
+ fi
18
+ else
19
+ # =============================================================================
20
+ # Package Installation
21
+ # =============================================================================
22
+ sudo apt install -y postgresql postgresql-contrib nginx
23
+
24
+ # =============================================================================
25
+ # Global Project Setup
26
+ # =============================================================================
27
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
28
+ echo " Setting up global project"
29
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
30
+
31
+ sudo mkdir -p /var/www
32
+ cd /var/www
33
+
34
+ ph init powerhouse
35
+ cd powerhouse
36
+ ph use $TARGET_TAG
37
+ ph connect build
38
+
39
+ # =============================================================================
40
+ # Interactive Package Installation
41
+ # =============================================================================
42
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
43
+ echo " Package Installation"
44
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
45
+ while true; do
46
+ read -p "Enter package name to install (or press Enter to skip): " package_name
47
+ if [ -z "$package_name" ]; then
48
+ break
49
+ fi
50
+ ph install "$package_name"
51
+ done
52
+
53
+ # =============================================================================
54
+ # Database Configuration
55
+ # =============================================================================
56
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
57
+ echo " Database Configuration"
58
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
59
+ echo "Choose database type:"
60
+ echo "1) Local PostgreSQL database"
61
+ echo "2) Remote PostgreSQL database"
62
+ read -p "Enter your choice (1 or 2): " db_choice
63
+
64
+ if [ "$db_choice" = "1" ]; then
65
+ echo "Setting up local PostgreSQL database..."
66
+
67
+ # Generate database credentials
68
+ DB_PASSWORD="powerhouse"
69
+ DB_USER="powerhouse"
70
+ DB_NAME="powerhouse"
71
+
72
+ # Create database and user
73
+ sudo -u postgres psql << EOF
74
+ CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
75
+ CREATE DATABASE $DB_NAME OWNER $DB_USER;
76
+ GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
77
+ EOF
78
+
79
+ # Configure PostgreSQL
80
+ sudo sed -i "s/#listen_addresses = 'localhost'/listen_addresses = 'localhost'/" /etc/postgresql/*/main/postgresql.conf
81
+
82
+ # Set DATABASE_URL for local database
83
+ DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost:5432/$DB_NAME"
84
+
85
+ echo "Local database configured successfully!"
86
+ echo "Database URL: $DATABASE_URL"
87
+ echo "Please save these credentials securely!"
88
+ else
89
+ echo "Enter remote PostgreSQL URL (format: postgresql://user:password@host:port/db)"
90
+ echo "Example: postgresql://powerhouse:password@db.example.com:5432/powerhouse"
91
+ read -p "DATABASE_URL: " DATABASE_URL
92
+ fi
93
+
94
+ # Save DATABASE_URL to .env file
95
+ echo "DATABASE_URL=$DATABASE_URL" | sudo tee -a /var/www/powerhouse/.env
96
+
97
+ # =============================================================================
98
+ # SSL Configuration
99
+ # =============================================================================
100
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
101
+ echo " SSL Configuration"
102
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
103
+ echo "Choose SSL configuration:"
104
+ echo "1) Let's Encrypt certificates for domains"
105
+ echo "2) Self-signed certificate for machine hostname"
106
+ read -p "Enter your choice (1 or 2): " ssl_choice
107
+
108
+ if [ "$ssl_choice" = "1" ]; then
109
+ # Install certbot
110
+ sudo apt install -y certbot python3-certbot-nginx
111
+
112
+ # =============================================================================
113
+ # Domain Setup
114
+ # =============================================================================
115
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
116
+ echo " Domain Setup"
117
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
118
+ read -p "Enter base domain (e.g. powerhouse.xyz): " base_domain
119
+ read -p "Enter subdomain for Connect service (default: connect): " connect_subdomain
120
+ read -p "Enter subdomain for Switchboard service (default: switchboard): " switchboard_subdomain
121
+
122
+ # Set default subdomains
123
+ connect_subdomain=${connect_subdomain:-connect}
124
+ switchboard_subdomain=${switchboard_subdomain:-switchboard}
125
+
126
+ # Construct full domains
127
+ connect_domain="${connect_subdomain}.${base_domain}"
128
+ switchboard_domain="${switchboard_subdomain}.${base_domain}"
129
+
130
+ echo "Using domains:"
131
+ echo "Connect: $connect_domain"
132
+ echo "Switchboard: $switchboard_domain"
133
+
134
+ # Generate temporary SSL certificates
135
+ echo "Generating temporary SSL certificates..."
136
+ sudo mkdir -p /etc/nginx/ssl
137
+ sudo openssl req -x509 -nodes -days 1 -newkey rsa:2048 \
138
+ -keyout /etc/nginx/ssl/temp.key \
139
+ -out /etc/nginx/ssl/temp.crt \
140
+ -subj "/CN=$base_domain" \
141
+ -addext "subjectAltName = DNS:$connect_domain,DNS:$switchboard_domain"
142
+
143
+ # Create Nginx configuration for domains
144
+ echo "Creating Nginx configuration..."
145
+ sudo tee /etc/nginx/sites-available/powerhouse > /dev/null << EOF
146
+ # Security headers
147
+ add_header Strict-Transport-Security "max-age=63072000" always;
148
+ add_header X-Frame-Options DENY;
149
+ add_header X-Content-Type-Options nosniff;
150
+ add_header X-XSS-Protection "1; mode=block";
151
+
152
+ server {
153
+ listen 80;
154
+ server_name $connect_domain $switchboard_domain;
155
+ return 301 https://\$host\$request_uri;
156
+ }
157
+
158
+ server {
159
+ listen 443 ssl http2;
160
+ server_name $connect_domain;
161
+
162
+ ssl_certificate /etc/nginx/ssl/temp.crt;
163
+ ssl_certificate_key /etc/nginx/ssl/temp.key;
164
+
165
+ # SSL configuration
166
+ ssl_protocols TLSv1.2 TLSv1.3;
167
+ 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;
168
+ ssl_prefer_server_ciphers off;
169
+ ssl_session_timeout 1d;
170
+ ssl_session_cache shared:SSL:50m;
171
+ ssl_session_tickets off;
172
+ ssl_stapling on;
173
+ ssl_stapling_verify on;
174
+
175
+ if (\$http_x_forwarded_proto = "http") {
176
+ return 301 https://\$server_name\$request_uri;
177
+ }
178
+
179
+ location / {
180
+ root /var/www/powerhouse/.ph/connect-build/dist;
181
+ try_files \$uri \$uri/ /index.html;
182
+ add_header Cache-Control "no-cache";
183
+ add_header X-Forwarded-Proto \$scheme;
184
+ add_header X-Forwarded-Host \$host;
185
+ add_header X-Forwarded-Port \$server_port;
186
+ }
187
+ }
188
+
189
+ server {
190
+ listen 443 ssl http2;
191
+ server_name $switchboard_domain;
192
+
193
+ ssl_certificate /etc/nginx/ssl/temp.crt;
194
+ ssl_certificate_key /etc/nginx/ssl/temp.key;
195
+
196
+ location / {
197
+ proxy_pass http://localhost:4001;
198
+ proxy_http_version 1.1;
199
+ proxy_set_header Upgrade \$http_upgrade;
200
+ proxy_set_header Connection 'upgrade';
201
+ proxy_set_header Host \$host;
202
+ proxy_cache_bypass \$http_upgrade;
203
+ proxy_set_header X-Real-IP \$remote_addr;
204
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
205
+ proxy_set_header X-Forwarded-Proto \$scheme;
206
+ }
207
+ }
208
+ EOF
209
+
210
+ # Enable the site
211
+ sudo ln -sf /etc/nginx/sites-available/powerhouse /etc/nginx/sites-enabled/
212
+ sudo rm -f /etc/nginx/sites-enabled/default
213
+
214
+ # Test and restart Nginx
215
+ sudo nginx -t
216
+ sudo systemctl restart nginx
217
+
218
+ # Obtain SSL certificates
219
+ echo "Obtaining SSL certificates..."
220
+ sudo certbot --nginx -d $connect_domain -d $switchboard_domain --non-interactive --agree-tos --email admin@$base_domain
221
+
222
+ # Remove temporary certificates
223
+ sudo rm -f /etc/nginx/ssl/temp.*
224
+
225
+ else
226
+ # Get machine hostname
227
+ hostname=$(hostname)
228
+
229
+ # Generate self-signed certificate
230
+ echo "Generating self-signed certificate for $hostname..."
231
+ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
232
+ -keyout /etc/ssl/private/$hostname.key \
233
+ -out /etc/ssl/certs/$hostname.crt \
234
+ -subj "/CN=$hostname" \
235
+ -addext "subjectAltName = DNS:$hostname"
236
+
237
+ # Create Nginx configuration for self-signed
238
+ echo "Creating Nginx configuration..."
239
+ sudo tee /etc/nginx/sites-available/powerhouse > /dev/null << EOF
240
+ # Security headers
241
+ add_header Strict-Transport-Security "max-age=63072000" always;
242
+ add_header X-Frame-Options DENY;
243
+ add_header X-Content-Type-Options nosniff;
244
+ add_header X-XSS-Protection "1; mode=block";
245
+
246
+ server {
247
+ listen 80;
248
+ server_name $hostname;
249
+ return 301 https://\$host\$request_uri;
250
+ }
251
+
252
+ server {
253
+ listen 443 ssl http2;
254
+ server_name $hostname;
255
+
256
+ ssl_certificate /etc/ssl/certs/$hostname.crt;
257
+ ssl_certificate_key /etc/ssl/private/$hostname.key;
258
+
259
+ location /connect {
260
+ proxy_pass http://localhost:3000;
261
+ proxy_http_version 1.1;
262
+ proxy_set_header Upgrade \$http_upgrade;
263
+ proxy_set_header Connection 'upgrade';
264
+ proxy_set_header Host \$host;
265
+ proxy_cache_bypass \$http_upgrade;
266
+ proxy_set_header X-Real-IP \$remote_addr;
267
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
268
+ proxy_set_header X-Forwarded-Proto \$scheme;
269
+ }
270
+
271
+ location /switchboard {
272
+ proxy_pass http://localhost:4001;
273
+ proxy_http_version 1.1;
274
+ proxy_set_header Upgrade \$http_upgrade;
275
+ proxy_set_header Connection 'upgrade';
276
+ proxy_set_header Host \$host;
277
+ proxy_cache_bypass \$http_upgrade;
278
+ proxy_set_header X-Real-IP \$remote_addr;
279
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
280
+ proxy_set_header X-Forwarded-Proto \$scheme;
281
+ }
282
+ }
283
+ EOF
284
+
285
+ # Enable the site
286
+ sudo ln -sf /etc/nginx/sites-available/powerhouse /etc/nginx/sites-enabled/
287
+ sudo rm -f /etc/nginx/sites-enabled/default
288
+
289
+ # Test and restart Nginx
290
+ sudo nginx -t
291
+ sudo systemctl restart nginx
292
+ fi
293
+
294
+ # =============================================================================
295
+ # Service Setup
296
+ # =============================================================================
297
+ # Install PM2 globally if not already installed
298
+ if ! command -v pm2 &> /dev/null; then
299
+ pnpm install -g pm2
300
+ fi
301
+
302
+ pnpm prisma db push --schema node_modules/document-drive/dist/prisma/schema.prisma
303
+ pnpm add @powerhousedao/switchboard@dev
304
+
305
+ # Start services with PM2
306
+ echo "Starting services with PM2..."
307
+ if [ "$ssl_choice" = "2" ]; then
308
+ # Self-signed certificate - use base paths
309
+ pm2 start pnpm switchboard --name "switchboard" -- --base-path /switchboard
310
+ else
311
+ # Let's Encrypt - no base paths needed
312
+ pm2 start "pnpm switchboard" --name "switchboard"
313
+ fi
314
+
315
+ # Save PM2 process list and setup startup script
316
+ pm2 save
317
+ pm2 startup
318
+ fi