UNPKG

@swell/cli

Version:

Swell's command line interface/utility

178 lines (177 loc) 8.69 kB
import { Flags } from '@oclif/core'; import { default as localConfig } from '../../../lib/config.js'; import style from '../../../lib/style.js'; import { PushAppCommand } from '../../../push-app-command.js'; import AppDev from '../dev.js'; export default class AppFrontendDev extends PushAppCommand { static examples = [ 'swell app frontend dev', 'swell app frontend dev --no-push', 'swell app frontend dev --proxy-port 3000', 'swell app frontend dev --storefront-select', 'swell app frontend dev --storefront-id <id>', ]; static flags = { ...AppDev.flags, 'proxy-port': Flags.integer({ description: 'specify the port for an existing frontend proxy', default: 3001, }), 'storefront-id': Flags.string({ description: 'identify a storefront to preview with and push theme files to', }), 'storefront-select': Flags.boolean({ default: false, description: 'prompt to select a storefront to preview with', }), 'app-dev': Flags.boolean({ description: 'indicates frontend app is running in app dev mode', default: true, }), }; static orientation = { env: 'test', }; static summary = `Run a frontend app in dev mode from your local machine.`; logAppLocalUrl(storeId, sessionId) { const frontendAppRoute = this.app.type === 'storefront' && this.app.storefront?.external ? `/${this.app.private_id}` : ''; this.log(`View it at ${style.link(`${this.localFrontendUrl(storeId, sessionId)}${frontendAppRoute}`)}\n`); } async run() { const { flags } = await this.parse(AppFrontendDev); const { port, 'proxy-port': proxyPort, 'app-dev': isAppDev } = flags; const noPush = flags['no-push']; if (!(await this.ensureAppExists(undefined, false))) { return; } if (!noPush && !isAppDev) { await this.pushAppConfigs(); } if (this.app.type === 'storefront') { await this.getStorefrontToPush(flags); this.logStorefrontConnected(); } this.saveCurrentStorefront(); if (!isAppDev) { this.log(`Starting app dev server...\n`); } const serverPort = await this.startProxyServer(proxyPort || port); await this.execFrontendProject(serverPort, isAppDev); } async execFrontendProject(serverPort, isAppDev) { const projectType = this.getFrontendProjectType(!isAppDev); if (!projectType) { return; } const currentStore = localConfig.getDefaultStore(); let serverReadyDetected = false; await this.execFrontend(projectType.devCommand.replace('${PORT}', String(serverPort)), (string) => { // Framework-specific output handling and ready detection switch (projectType.slug) { case 'nextjs': { // 1. NOISE FILTER: Hide unwanted output if (string.includes('Using vars defined in .dev.vars')) { return false; } // 2. URL FILTER: Hide localhost/network URLs (confusing - users should use Swell tunnel) if (/- local:\s+http:\/\//i.test(string) || /- network:\s+http:\/\//i.test(string) || /ready on http:\/\/localhost/i.test(string)) { return false; } // 3. READY DETECTION: Detect server ready, show our message if (!serverReadyDetected && (/✓ ready in \d+/.test(string) || /✓ starting/.test(string))) { serverReadyDetected = true; this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`); const sessionId = localConfig.getSessionId(currentStore); setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100); if (!isAppDev) { this.watchForChanges(); } } break; } case 'astro': { // 2. URL FILTER: Hide localhost/network URLs (confusing - users should use Swell tunnel) if (string.includes('┃ Local') || string.includes('┃ Network')) { return false; } // 3. READY DETECTION: Detect server ready, show our message if (!serverReadyDetected && /watching for file changes/i.test(string)) { serverReadyDetected = true; this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`); const sessionId = localConfig.getSessionId(currentStore); setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100); if (!isAppDev) { this.watchForChanges(); } } break; } case 'angular': { // 1. NOISE FILTER: Hide unwanted output if (string.includes('press h + enter to show help')) { return false; } // 2. URL FILTER: Hide localhost/network URLs (confusing - users should use Swell tunnel) if (/➜\s+local:\s+http:\/\//i.test(string)) { return false; } // 3. READY DETECTION: Detect server ready, show our message if (!serverReadyDetected && (/application bundle generation complete/.test(string) || /watch mode enabled/.test(string))) { serverReadyDetected = true; this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`); const sessionId = localConfig.getSessionId(currentStore); setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100); if (!isAppDev) { this.watchForChanges(); } } break; } case 'hono': { // 2. URL FILTER: Hide localhost URLs (confusing - users should use Swell tunnel) // Note: For Hono, the ready signal IS the URL line, so we handle both in section 3 // 3. READY DETECTION: Detect server ready, show our message, hide the URL if (!serverReadyDetected && /ready on http:\/\/localhost:\d+/i.test(string)) { serverReadyDetected = true; this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`); const sessionId = localConfig.getSessionId(currentStore); setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100); if (!isAppDev) { this.watchForChanges(); } return false; // Hide the "Ready on localhost" line } break; } case 'nuxt': { // 2. URL FILTER: Hide localhost/network URLs (confusing - users should use Swell tunnel) if (/➜ local:\s+http:\/\//i.test(string) || /➜ network:/i.test(string)) { return false; } // 3. READY DETECTION: Detect server ready, show our message if (!serverReadyDetected && /nuxt \d+\.\d+\.\d+/i.test(string)) { serverReadyDetected = true; this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`); const sessionId = localConfig.getSessionId(currentStore); setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100); if (!isAppDev) { this.watchForChanges(); } } break; } // No default } }); } }