Skip to content

Commit 8ccd8fb

Browse files
Add separate frontend and backend port configuration for demo command
Implement ATXP-243: Allow users to specify separate frontend and backend ports when running the demo, replacing the single --port option with more granular control. ## Changes Made ### Command Line Interface - Replace `--port, -p` with `--frontend-port, --fp` and `--backend-port, --bp` - Update default ports: frontend 3000, backend 3001 (matching atxp-express-example defaults) - Maintain backward compatibility by using sensible defaults ### Configuration Management - Generate .env files for both frontend and backend directories with appropriate port settings - Backend .env: `PORT` and `FRONTEND_PORT` (for CORS configuration) - Frontend .env: `PORT` and `REACT_APP_BACKEND_PORT` (for proxy configuration) - Graceful fallback if .env creation fails (uses environment variables) ### Updated Documentation - Comprehensive help text with new port options and examples - Clear usage examples showing frontend/backend port combinations - Updated default port information throughout ## Implementation Details The demo command now: 1. Parses separate frontend/backend port arguments 2. Creates appropriate .env files in the cloned repository 3. Passes environment variables to the demo process 4. Uses frontend port for browser opening and user messaging This integrates seamlessly with the atxp-express-example repository's existing port configuration system implemented in PR #6. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent ec9b09e commit 8ccd8fb

File tree

3 files changed

+70
-19
lines changed

3 files changed

+70
-19
lines changed

packages/atxp/src/help.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,21 @@ export function showHelp(): void {
1616
console.log();
1717

1818
console.log(chalk.bold('Demo Options:'));
19-
console.log(' ' + chalk.yellow('--verbose, -v') + ' ' + 'Show detailed logs');
20-
console.log(' ' + chalk.yellow('--refresh') + ' ' + 'Force refresh the demo from GitHub');
21-
console.log(' ' + chalk.yellow('--port, -p') + ' ' + 'Specify port number (default: 8016)');
22-
console.log(' ' + chalk.yellow('--dir, -d') + ' ' + 'Specify demo directory (default: ~/.cache/atxp/demo)');
19+
console.log(' ' + chalk.yellow('--verbose, -v') + ' ' + 'Show detailed logs');
20+
console.log(' ' + chalk.yellow('--refresh') + ' ' + 'Force refresh the demo from GitHub');
21+
console.log(' ' + chalk.yellow('--frontend-port, --fp') + ' ' + 'Specify frontend port (default: 3000)');
22+
console.log(' ' + chalk.yellow('--backend-port, --bp') + ' ' + 'Specify backend port (default: 3001)');
23+
console.log(' ' + chalk.yellow('--dir, -d') + ' ' + 'Specify demo directory (default: ~/.cache/atxp/demo)');
2324
console.log();
2425

2526
console.log(chalk.bold('Examples:'));
26-
console.log(' npx atxp demo # Run the demo with defaults');
27+
console.log(' npx atxp demo # Run the demo with defaults (frontend: 3000, backend: 3001)');
2728
console.log(' npx atxp demo --verbose # Run demo with detailed logs');
28-
console.log(' npx atxp demo --port 3000 # Run demo on port 3000');
29+
console.log(' npx atxp demo --frontend-port 4000 # Run demo with frontend on port 4000');
30+
console.log(' npx atxp demo --backend-port 4001 # Run demo with backend on port 4001');
2931
console.log(' npx atxp demo --dir ./my-demo # Use custom demo directory');
30-
console.log(' npx atxp demo --port 3000 --dir ./demo # Custom port and directory');
32+
console.log(' npx atxp demo --frontend-port 4000 --backend-port 4001 # Custom ports');
33+
console.log(' npx atxp demo --dir ./my-demo --frontend-port 4000 # Custom directory and port');
3134
console.log(' npx atxp create # Create a new project');
3235
console.log();
3336

packages/atxp/src/index.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { showHelp } from './help.js';
88
import { checkAllDependencies, showDependencyError } from './check-dependencies.js';
99

1010
interface DemoOptions {
11-
port: number;
11+
frontendPort: number;
12+
backendPort: number;
1213
dir: string;
1314
verbose: boolean;
1415
refresh: boolean;
@@ -24,13 +25,22 @@ function parseArgs(): { command: string; demoOptions: DemoOptions } {
2425
return index !== -1 ? process.argv[index + 1] : undefined;
2526
};
2627

27-
const port = (() => {
28-
const portValue = getArgValue('--port', '-p');
28+
const frontendPort = (() => {
29+
const portValue = getArgValue('--frontend-port', '--fp');
2930
if (portValue) {
3031
const parsed = parseInt(portValue, 10);
3132
if (parsed > 0 && parsed < 65536) return parsed;
3233
}
33-
return 8016; // default port
34+
return 3000; // default frontend port
35+
})();
36+
37+
const backendPort = (() => {
38+
const portValue = getArgValue('--backend-port', '--bp');
39+
if (portValue) {
40+
const parsed = parseInt(portValue, 10);
41+
if (parsed > 0 && parsed < 65536) return parsed;
42+
}
43+
return 3001; // default backend port
3444
})();
3545

3646
const dir = (() => {
@@ -43,7 +53,7 @@ function parseArgs(): { command: string; demoOptions: DemoOptions } {
4353

4454
return {
4555
command,
46-
demoOptions: { port, dir, verbose, refresh }
56+
demoOptions: { frontendPort, backendPort, dir, verbose, refresh }
4757
};
4858
}
4959

packages/atxp/src/run-demo.ts

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import chalk from 'chalk';
22
import { spawn } from 'child_process';
33
import fs from 'fs-extra';
44
import open from 'open';
5+
import path from 'path';
56

67
interface DemoOptions {
7-
port: number;
8+
frontendPort: number;
9+
backendPort: number;
810
dir: string;
911
verbose: boolean;
1012
refresh: boolean;
@@ -32,8 +34,11 @@ export async function runDemo(options: DemoOptions): Promise<void> {
3234
// Install dependencies if needed
3335
await installDependencies(options.dir, options.verbose);
3436

37+
// Create .env files for configuration
38+
await createEnvFiles(options.dir, options.frontendPort, options.backendPort, options.verbose);
39+
3540
// Start the demo and open browser
36-
await startDemo(options.port, options.dir, options.verbose);
41+
await startDemo(options.frontendPort, options.backendPort, options.dir, options.verbose);
3742

3843
} catch (error) {
3944
console.error(chalk.red('Error starting demo:'), (error as Error).message);
@@ -124,9 +129,9 @@ async function installDependencies(demoDir: string, isVerbose: boolean): Promise
124129
});
125130
}
126131

127-
async function startDemo(port: number, demoDir: string, isVerbose: boolean): Promise<void> {
132+
async function startDemo(frontendPort: number, backendPort: number, demoDir: string, isVerbose: boolean): Promise<void> {
128133
console.log(chalk.blue('Starting demo application...'));
129-
console.log(chalk.green(`Demo will be available at: http://localhost:${port}`));
134+
console.log(chalk.green(`Demo will be available at: http://localhost:${frontendPort}`));
130135
console.log(chalk.gray(`Demo directory: ${demoDir}`));
131136
console.log(chalk.yellow('Press Ctrl+C to stop the demo'));
132137
if (!isVerbose) {
@@ -137,7 +142,10 @@ async function startDemo(port: number, demoDir: string, isVerbose: boolean): Pro
137142
// Set the port environment variable for the demo
138143
const env = {
139144
...process.env,
140-
PORT: port.toString(),
145+
PORT: frontendPort.toString(),
146+
FRONTEND_PORT: frontendPort.toString(),
147+
BACKEND_PORT: backendPort.toString(),
148+
REACT_APP_BACKEND_PORT: backendPort.toString(),
141149
// Suppress deprecation warnings
142150
NODE_NO_WARNINGS: '1',
143151
// Suppress React warnings in development
@@ -190,10 +198,10 @@ async function startDemo(port: number, demoDir: string, isVerbose: boolean): Pro
190198
if (!demoOpenedBrowser) {
191199
try {
192200
console.log(chalk.blue('Opening browser...'));
193-
await open(`http://localhost:${port}`);
201+
await open(`http://localhost:${frontendPort}`);
194202
} catch {
195203
console.log(chalk.yellow('Could not open browser automatically'));
196-
console.log(chalk.white(`Please open http://localhost:${port} in your browser`));
204+
console.log(chalk.white(`Please open http://localhost:${frontendPort} in your browser`));
197205
}
198206
}
199207
}, 2000);
@@ -224,6 +232,36 @@ async function startDemo(port: number, demoDir: string, isVerbose: boolean): Pro
224232
});
225233
}
226234

235+
async function createEnvFiles(demoDir: string, frontendPort: number, backendPort: number, isVerbose: boolean): Promise<void> {
236+
if (isVerbose) {
237+
console.log(chalk.blue('Creating .env files...'));
238+
}
239+
240+
try {
241+
// Create backend .env file
242+
const backendEnvPath = path.join(demoDir, 'backend', '.env');
243+
const backendEnvContent = `PORT=${backendPort}\nFRONTEND_PORT=${frontendPort}\n`;
244+
await fs.writeFile(backendEnvPath, backendEnvContent);
245+
246+
if (isVerbose) {
247+
console.log(chalk.gray(`Created backend .env: ${backendEnvPath}`));
248+
}
249+
250+
// Create frontend .env file
251+
const frontendEnvPath = path.join(demoDir, 'frontend', '.env');
252+
const frontendEnvContent = `PORT=${frontendPort}\nREACT_APP_BACKEND_PORT=${backendPort}\n`;
253+
await fs.writeFile(frontendEnvPath, frontendEnvContent);
254+
255+
if (isVerbose) {
256+
console.log(chalk.gray(`Created frontend .env: ${frontendEnvPath}`));
257+
}
258+
259+
} catch (error) {
260+
console.log(chalk.yellow(`Warning: Could not create .env files: ${(error as Error).message}`));
261+
console.log(chalk.gray('Demo will use environment variables passed directly'));
262+
}
263+
}
264+
227265
async function cleanup(): Promise<void> {
228266
try {
229267
// Optionally clean up the demo directory

0 commit comments

Comments
 (0)