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

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.2",
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,320 @@
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 --$TARGET_TAG
35
+ cd powerhouse
36
+
37
+ # =============================================================================
38
+ # Interactive Package Installation
39
+ # =============================================================================
40
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
41
+ echo " Package Installation"
42
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
43
+ while true; do
44
+ read -p "Enter package name to install (or press Enter to skip): " package_name
45
+ if [ -z "$package_name" ]; then
46
+ break
47
+ fi
48
+ ph install "$package_name"
49
+ done
50
+
51
+ # =============================================================================
52
+ # Connect Build
53
+ # =============================================================================
54
+ ph connect build
55
+
56
+ # =============================================================================
57
+ # Database Configuration
58
+ # =============================================================================
59
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
60
+ echo " Database Configuration"
61
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
62
+ echo "Choose database type:"
63
+ echo "1) Local PostgreSQL database"
64
+ echo "2) Remote PostgreSQL database"
65
+ read -p "Enter your choice (1 or 2): " db_choice
66
+
67
+ if [ "$db_choice" = "1" ]; then
68
+ echo "Setting up local PostgreSQL database..."
69
+
70
+ # Generate database credentials
71
+ DB_PASSWORD="powerhouse"
72
+ DB_USER="powerhouse"
73
+ DB_NAME="powerhouse"
74
+
75
+ # Create database and user
76
+ sudo -u postgres psql << EOF
77
+ CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
78
+ CREATE DATABASE $DB_NAME OWNER $DB_USER;
79
+ GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
80
+ EOF
81
+
82
+ # Configure PostgreSQL
83
+ sudo sed -i "s/#listen_addresses = 'localhost'/listen_addresses = 'localhost'/" /etc/postgresql/*/main/postgresql.conf
84
+
85
+ # Set DATABASE_URL for local database
86
+ DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost:5432/$DB_NAME"
87
+
88
+ echo "Local database configured successfully!"
89
+ echo "Database URL: $DATABASE_URL"
90
+ echo "Please save these credentials securely!"
91
+ else
92
+ echo "Enter remote PostgreSQL URL (format: postgresql://user:password@host:port/db)"
93
+ echo "Example: postgresql://powerhouse:password@db.example.com:5432/powerhouse"
94
+ read -p "DATABASE_URL: " DATABASE_URL
95
+ fi
96
+
97
+ # Save DATABASE_URL to .env file
98
+ echo "DATABASE_URL=$DATABASE_URL" | sudo tee -a /var/www/powerhouse/.env
99
+
100
+ # =============================================================================
101
+ # SSL Configuration
102
+ # =============================================================================
103
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
104
+ echo " SSL Configuration"
105
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
106
+ echo "Choose SSL configuration:"
107
+ echo "1) Let's Encrypt certificates for domains"
108
+ echo "2) Self-signed certificate for machine hostname"
109
+ read -p "Enter your choice (1 or 2): " ssl_choice
110
+
111
+ if [ "$ssl_choice" = "1" ]; then
112
+ # Install certbot
113
+ sudo apt install -y certbot python3-certbot-nginx
114
+
115
+ # =============================================================================
116
+ # Domain Setup
117
+ # =============================================================================
118
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
119
+ echo " Domain Setup"
120
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
121
+ read -p "Enter base domain (e.g. powerhouse.xyz): " base_domain
122
+ read -p "Enter subdomain for Connect service (default: connect): " connect_subdomain
123
+ read -p "Enter subdomain for Switchboard service (default: switchboard): " switchboard_subdomain
124
+
125
+ # Set default subdomains
126
+ connect_subdomain=${connect_subdomain:-connect}
127
+ switchboard_subdomain=${switchboard_subdomain:-switchboard}
128
+
129
+ # Construct full domains
130
+ connect_domain="${connect_subdomain}.${base_domain}"
131
+ switchboard_domain="${switchboard_subdomain}.${base_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=$base_domain" \
144
+ -addext "subjectAltName = DNS:$connect_domain,DNS:$switchboard_domain"
145
+
146
+ # Create Nginx configuration for domains
147
+ echo "Creating Nginx configuration..."
148
+ sudo tee /etc/nginx/sites-available/powerhouse > /dev/null << EOF
149
+ # Security headers
150
+ add_header Strict-Transport-Security "max-age=63072000" always;
151
+ add_header X-Frame-Options DENY;
152
+ add_header X-Content-Type-Options nosniff;
153
+ add_header X-XSS-Protection "1; mode=block";
154
+
155
+ server {
156
+ listen 80;
157
+ server_name $connect_domain $switchboard_domain;
158
+ return 301 https://\$host\$request_uri;
159
+ }
160
+
161
+ server {
162
+ listen 443 ssl http2;
163
+ server_name $connect_domain;
164
+
165
+ ssl_certificate /etc/nginx/ssl/temp.crt;
166
+ ssl_certificate_key /etc/nginx/ssl/temp.key;
167
+
168
+ # SSL configuration
169
+ ssl_protocols TLSv1.2 TLSv1.3;
170
+ 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;
171
+ ssl_prefer_server_ciphers off;
172
+ ssl_session_timeout 1d;
173
+ ssl_session_cache shared:SSL:50m;
174
+ ssl_session_tickets off;
175
+ ssl_stapling on;
176
+ ssl_stapling_verify on;
177
+
178
+ if (\$http_x_forwarded_proto = "http") {
179
+ return 301 https://\$server_name\$request_uri;
180
+ }
181
+
182
+ location / {
183
+ root /var/www/powerhouse/.ph/connect-build/dist;
184
+ try_files \$uri \$uri/ /index.html;
185
+ add_header Cache-Control "no-cache";
186
+ add_header X-Forwarded-Proto \$scheme;
187
+ add_header X-Forwarded-Host \$host;
188
+ add_header X-Forwarded-Port \$server_port;
189
+ }
190
+ }
191
+
192
+ server {
193
+ listen 443 ssl http2;
194
+ server_name $switchboard_domain;
195
+
196
+ ssl_certificate /etc/nginx/ssl/temp.crt;
197
+ ssl_certificate_key /etc/nginx/ssl/temp.key;
198
+
199
+ location / {
200
+ proxy_pass http://localhost:4001;
201
+ proxy_http_version 1.1;
202
+ proxy_set_header Upgrade \$http_upgrade;
203
+ proxy_set_header Connection 'upgrade';
204
+ proxy_set_header Host \$host;
205
+ proxy_cache_bypass \$http_upgrade;
206
+ proxy_set_header X-Real-IP \$remote_addr;
207
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
208
+ proxy_set_header X-Forwarded-Proto \$scheme;
209
+ }
210
+ }
211
+ EOF
212
+
213
+ # Enable the site
214
+ sudo ln -sf /etc/nginx/sites-available/powerhouse /etc/nginx/sites-enabled/
215
+ sudo rm -f /etc/nginx/sites-enabled/default
216
+
217
+ # Test and restart Nginx
218
+ sudo nginx -t
219
+ sudo systemctl restart nginx
220
+
221
+ # Obtain SSL certificates
222
+ echo "Obtaining SSL certificates..."
223
+ sudo certbot --nginx -d $connect_domain -d $switchboard_domain --non-interactive --agree-tos --email admin@$base_domain
224
+
225
+ # Remove temporary certificates
226
+ sudo rm -f /etc/nginx/ssl/temp.*
227
+
228
+ else
229
+ # Get machine hostname
230
+ hostname=$(hostname)
231
+
232
+ # Generate self-signed certificate
233
+ echo "Generating self-signed certificate for $hostname..."
234
+ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
235
+ -keyout /etc/ssl/private/$hostname.key \
236
+ -out /etc/ssl/certs/$hostname.crt \
237
+ -subj "/CN=$hostname" \
238
+ -addext "subjectAltName = DNS:$hostname"
239
+
240
+ # Create Nginx configuration for self-signed
241
+ echo "Creating Nginx configuration..."
242
+ sudo tee /etc/nginx/sites-available/powerhouse > /dev/null << EOF
243
+ # Security headers
244
+ add_header Strict-Transport-Security "max-age=63072000" always;
245
+ add_header X-Frame-Options DENY;
246
+ add_header X-Content-Type-Options nosniff;
247
+ add_header X-XSS-Protection "1; mode=block";
248
+
249
+ server {
250
+ listen 80;
251
+ server_name $hostname;
252
+ return 301 https://\$host\$request_uri;
253
+ }
254
+
255
+ server {
256
+ listen 443 ssl http2;
257
+ server_name $hostname;
258
+
259
+ ssl_certificate /etc/ssl/certs/$hostname.crt;
260
+ ssl_certificate_key /etc/ssl/private/$hostname.key;
261
+
262
+ location /connect {
263
+ proxy_pass http://localhost:3000;
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
+ location /switchboard {
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
+
288
+ # Enable the site
289
+ sudo ln -sf /etc/nginx/sites-available/powerhouse /etc/nginx/sites-enabled/
290
+ sudo rm -f /etc/nginx/sites-enabled/default
291
+
292
+ # Test and restart Nginx
293
+ sudo nginx -t
294
+ sudo systemctl restart nginx
295
+ fi
296
+
297
+ # =============================================================================
298
+ # Service Setup
299
+ # =============================================================================
300
+ # Install PM2 globally if not already installed
301
+ if ! command -v pm2 &> /dev/null; then
302
+ pnpm install -g pm2
303
+ fi
304
+
305
+ pnpm prisma db push --schema node_modules/document-drive/dist/prisma/schema.prisma
306
+
307
+ # Start services with PM2
308
+ echo "Starting services with PM2..."
309
+ if [ "$ssl_choice" = "2" ]; then
310
+ # Self-signed certificate - use base paths
311
+ pm2 start pnpm switchboard --name "switchboard" -- --base-path /switchboard
312
+ else
313
+ # Let's Encrypt - no base paths needed
314
+ pm2 start "pnpm switchboard" --name "switchboard"
315
+ fi
316
+
317
+ # Save PM2 process list and setup startup script
318
+ pm2 save
319
+ pm2 startup
320
+ fi