Skip to content

Commit

Permalink
Add logic to represent booting state within preview panel and parse s…
Browse files Browse the repository at this point in the history
…tdout from vite to get port (srcbookdev#349)

* feat: add logic to represent booting state within preview panel and parse stdout from vite to get port

* fix: run npm run format
  • Loading branch information
1egoman authored and BeRecursive22 committed Oct 13, 2024
1 parent 09b1b82 commit e53e18a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 32 deletions.
64 changes: 44 additions & 20 deletions packages/api/server/channels/app.mts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@ import { loadApp } from '../../apps/app.mjs';
import { fileUpdated, pathToApp } from '../../apps/disk.mjs';
import { vite } from '../../exec.mjs';

const VITE_PORT_REGEX = /Local:.*http:\/\/localhost:([0-9]{1,4})/;

type AppContextType = MessageContextType<'appId'>;

const processes = new Map<string, ChildProcess>();
type ProcessMetadata = {
process: ChildProcess;
port: number | null;
};

const processMetadata = new Map<string, ProcessMetadata>();

async function previewStart(
_payload: PreviewStartPayloadType,
Expand All @@ -33,41 +40,56 @@ async function previewStart(
return;
}

const existingProcess = processes.get(app.externalId);
const existingProcess = processMetadata.get(app.externalId);

if (existingProcess) {
conn.reply(`app:${app.externalId}`, 'preview:status', { url: null, status: 'running' });
conn.reply(`app:${app.externalId}`, 'preview:status', {
status: 'running',
url: `http://localhost:${existingProcess.port}/`,
});
return;
}

conn.reply(`app:${app.externalId}`, 'preview:status', {
url: null,
status: 'booting',
});

const onChangePort = (newPort: number) => {
processMetadata.set(app.externalId, { process, port: newPort });
conn.reply(`app:${app.externalId}`, 'preview:status', {
url: `http://localhost:${newPort}/`,
status: 'running',
});
};

const process = vite({
// TODO: Configure port and fail if port in use
args: [],
cwd: pathToApp(app.externalId),
stdout: (data) => {
console.log(data.toString('utf8'));
const encodedData = data.toString('utf8');
console.log(encodedData);

const potentialPortMatch = VITE_PORT_REGEX.exec(encodedData);
if (potentialPortMatch) {
const portString = potentialPortMatch[1]!;
const port = parseInt(portString, 10);
onChangePort(port);
}
},
stderr: (data) => {
console.error(data.toString('utf8'));
},
onExit: (_code) => {
processes.delete(app.externalId);
processMetadata.delete(app.externalId);
conn.reply(`app:${app.externalId}`, 'preview:status', {
url: null,
status: 'stopped',
});
},
});

processes.set(app.externalId, process);

// TODO: better way to know when the server is ready
setTimeout(() => {
conn.reply(`app:${app.externalId}`, 'preview:status', {
url: 'http://localhost:5174/',
status: 'running',
});
}, 500);
processMetadata.set(app.externalId, { process, port: null });
}

async function previewStop(
Expand All @@ -81,14 +103,14 @@ async function previewStop(
return;
}

const process = processes.get(app.externalId);
const result = processMetadata.get(app.externalId);

if (!process) {
if (!result) {
conn.reply(`app:${app.externalId}`, 'preview:status', { url: null, status: 'stopped' });
return;
}

process.kill('SIGTERM');
result.process.kill('SIGTERM');

conn.reply(`app:${app.externalId}`, 'preview:status', { url: null, status: 'stopped' });
}
Expand Down Expand Up @@ -117,13 +139,15 @@ export function register(wss: WebSocketServer) {
return;
}

const existingProcess = processes.get(app.externalId);
const existingProcess = processMetadata.get(app.externalId);

ws.send(
JSON.stringify([
topic,
'preview:status',
{ url: null, status: existingProcess ? 'running' : 'stopped' },
existingProcess
? { status: 'running', url: `http://localhost:${existingProcess.port}/` }
: { url: null, status: 'stopped' },
]),
);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/components/apps/use-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { createContext, useContext, useEffect, useState } from 'react';
import { AppChannel } from '@/clients/websocket';
import { PreviewStatusPayloadType } from '@srcbook/shared';

export type PreviewStatusType = 'connecting' | 'booting' | 'running' | 'stopped';
export type PreviewStatusType = 'booting' | 'connecting' | 'running' | 'stopped';

export interface PreviewContextValue {
url: string | null;
Expand Down
30 changes: 21 additions & 9 deletions packages/web/src/components/apps/workspace/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,27 @@ type PropsType = {
};

export function Preview(props: PropsType) {
const { url } = usePreview();
const { url, status } = usePreview();

if (url === null) {
return;
}
switch (status) {
case 'connecting':
case 'booting':
return (
<div className={cn('flex justify-center items-center w-full h-full', props.className)}>
<span className="text-tertiary-foreground">Booting...</span>
</div>
);
case 'running':
if (url === null) {
return;
}

return (
<div className={cn(props.className)}>
<iframe className="w-full h-full" src={url} title="App preview" />
</div>
);
return (
<div className={cn(props.className)}>
<iframe className="w-full h-full" src={url} title="App preview" />
</div>
);
case 'stopped':
return null;
}
}
5 changes: 3 additions & 2 deletions packages/web/src/routes/apps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,19 @@ export function AppsPage() {

function Apps(props: { app: AppType }) {
const { status: previewStatus } = usePreview();
const previewVisible = previewStatus === 'booting' || previewStatus === 'running';

return (
<div className="h-screen max-h-screen flex">
<Sidebar />
<div
className={cn(
'w-full h-full grid divide-x divide-border',
previewStatus === 'running' ? 'grid-cols-2' : 'grid-cols-1',
previewVisible ? 'grid-cols-2' : 'grid-cols-1',
)}
>
<Editor app={props.app} />
{previewStatus === 'running' && <Preview />}
{previewVisible ? <Preview /> : null}
</div>
</div>
);
Expand Down

0 comments on commit e53e18a

Please sign in to comment.