Merge pull request #97 from jonathanhefner/running-all-examples
Add `examples/run-all.ts` script
This commit is contained in:
commit
4736621512
8 changed files with 259 additions and 158 deletions
|
|
@ -18,6 +18,7 @@ const __dirname = dirname(__filename);
|
|||
const HOST_PORT = parseInt(process.env.HOST_PORT || "8080", 10);
|
||||
const SANDBOX_PORT = parseInt(process.env.SANDBOX_PORT || "8081", 10);
|
||||
const DIRECTORY = join(__dirname, "dist");
|
||||
const SERVERS: string[] = process.env.SERVERS ? JSON.parse(process.env.SERVERS) : [];
|
||||
|
||||
// ============ Host Server (port 8080) ============
|
||||
const hostApp = express();
|
||||
|
|
@ -34,6 +35,11 @@ hostApp.use((req, res, next) => {
|
|||
|
||||
hostApp.use(express.static(DIRECTORY));
|
||||
|
||||
// API endpoint to get configured server URLs
|
||||
hostApp.get("/api/servers", (_req, res) => {
|
||||
res.json(SERVERS);
|
||||
});
|
||||
|
||||
hostApp.get("/", (_req, res) => {
|
||||
res.redirect("/index.html");
|
||||
});
|
||||
|
|
@ -70,7 +76,7 @@ sandboxApp.use((_req, res) => {
|
|||
});
|
||||
|
||||
// ============ Start both servers ============
|
||||
hostApp.listen(HOST_PORT, err => {
|
||||
hostApp.listen(HOST_PORT, (err) => {
|
||||
if (err) {
|
||||
console.error("Error starting server:", err);
|
||||
process.exit(1);
|
||||
|
|
@ -78,7 +84,7 @@ hostApp.listen(HOST_PORT, err => {
|
|||
console.log(`Host server: http://localhost:${HOST_PORT}`);
|
||||
});
|
||||
|
||||
sandboxApp.listen(SANDBOX_PORT, err => {
|
||||
sandboxApp.listen(SANDBOX_PORT, (err) => {
|
||||
if (err) {
|
||||
console.error("Error starting server:", err);
|
||||
process.exit(1);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ export const log = {
|
|||
|
||||
|
||||
export interface ServerInfo {
|
||||
name: string;
|
||||
client: Client;
|
||||
tools: Map<string, Tool>;
|
||||
appHtmlCache: Map<string, string>;
|
||||
|
|
@ -30,11 +31,13 @@ export async function connectToServer(serverUrl: URL): Promise<ServerInfo> {
|
|||
await client.connect(new StreamableHTTPClientTransport(serverUrl));
|
||||
log.info("Connection successful");
|
||||
|
||||
const name = client.getServerVersion()?.name ?? serverUrl.href;
|
||||
|
||||
const toolsList = await client.listTools();
|
||||
const tools = new Map(toolsList.tools.map((tool) => [tool.name, tool]));
|
||||
log.info("Server tools:", Array.from(tools.keys()));
|
||||
|
||||
return { client, tools, appHtmlCache: new Map() };
|
||||
return { name, client, tools, appHtmlCache: new Map() };
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,3 @@
|
|||
.connecting {
|
||||
padding: 1rem 0;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.callToolPanel, .toolCallInfoPanel {
|
||||
margin: 0 auto;
|
||||
padding: 1rem;
|
||||
|
|
@ -16,9 +10,6 @@
|
|||
}
|
||||
|
||||
.callToolPanel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
max-width: 480px;
|
||||
|
||||
form {
|
||||
|
|
@ -39,12 +30,16 @@
|
|||
padding: 0.5rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
textarea {
|
||||
.toolSelect {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.toolInput {
|
||||
min-height: 6rem;
|
||||
font-family: monospace;
|
||||
resize: vertical;
|
||||
|
||||
&[aria-invalid="true"] {
|
||||
|
|
@ -92,10 +87,15 @@
|
|||
gap: 0.5rem;
|
||||
min-width: 0;
|
||||
|
||||
.toolName {
|
||||
h2 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
font-family: monospace;
|
||||
font-size: 1.5rem;
|
||||
|
||||
.toolName {
|
||||
font-family: monospace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,118 +4,39 @@ import { callTool, connectToServer, hasAppHtml, initializeApp, loadSandboxProxy,
|
|||
import styles from "./index.module.css";
|
||||
|
||||
|
||||
// Available MCP servers - using ports 3101+ to avoid conflicts with common dev ports
|
||||
const SERVERS = [
|
||||
{ name: "Basic React", port: 3101 },
|
||||
{ name: "Vanilla JS", port: 3102 },
|
||||
{ name: "Budget Allocator", port: 3103 },
|
||||
{ name: "Cohort Heatmap", port: 3104 },
|
||||
{ name: "Customer Segmentation", port: 3105 },
|
||||
{ name: "Scenario Modeler", port: 3106 },
|
||||
{ name: "System Monitor", port: 3107 },
|
||||
{ name: "Three.js", port: 3109 },
|
||||
] as const;
|
||||
|
||||
function serverUrl(port: number): string {
|
||||
return `http://localhost:${port}/mcp`;
|
||||
// Host passes serversPromise to CallToolPanel
|
||||
interface HostProps {
|
||||
serversPromise: Promise<ServerInfo[]>;
|
||||
}
|
||||
|
||||
// Cache server connections to avoid reconnecting when switching between servers
|
||||
const serverInfoCache = new Map<number, Promise<ServerInfo>>();
|
||||
|
||||
function getServerInfo(port: number): Promise<ServerInfo> {
|
||||
let promise = serverInfoCache.get(port);
|
||||
if (!promise) {
|
||||
promise = connectToServer(new URL(serverUrl(port)));
|
||||
// Remove from cache on failure so retry is possible
|
||||
promise.catch(() => serverInfoCache.delete(port));
|
||||
serverInfoCache.set(port, promise);
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
||||
// Wrapper to track server name with each tool call
|
||||
interface ToolCallEntry {
|
||||
serverName: string;
|
||||
info: ToolCallInfo;
|
||||
}
|
||||
|
||||
// Host just manages tool call results - no server dependency
|
||||
function Host() {
|
||||
const [toolCalls, setToolCalls] = useState<ToolCallEntry[]>([]);
|
||||
function Host({ serversPromise }: HostProps) {
|
||||
const [toolCalls, setToolCalls] = useState<ToolCallInfo[]>([]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{toolCalls.map((entry, i) => (
|
||||
<ToolCallInfoPanel key={i} serverName={entry.serverName} toolCallInfo={entry.info} />
|
||||
{toolCalls.map((info, i) => (
|
||||
<ToolCallInfoPanel key={i} toolCallInfo={info} />
|
||||
))}
|
||||
<CallToolPanel
|
||||
addToolCall={(serverName, info) => setToolCalls([...toolCalls, { serverName, info }])}
|
||||
serversPromise={serversPromise}
|
||||
addToolCall={(info) => setToolCalls([...toolCalls, info])}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// CallToolPanel includes server selection with its own Suspense boundary
|
||||
// CallToolPanel renders the unified form with Suspense around ServerSelect
|
||||
interface CallToolPanelProps {
|
||||
addToolCall: (serverName: string, info: ToolCallInfo) => void;
|
||||
serversPromise: Promise<ServerInfo[]>;
|
||||
addToolCall: (info: ToolCallInfo) => void;
|
||||
}
|
||||
function CallToolPanel({ addToolCall }: CallToolPanelProps) {
|
||||
const [selectedServer, setSelectedServer] = useState(SERVERS[0]);
|
||||
const [serverInfoPromise, setServerInfoPromise] = useState(
|
||||
() => getServerInfo(selectedServer.port)
|
||||
);
|
||||
|
||||
const handleServerChange = (port: number) => {
|
||||
const server = SERVERS.find(s => s.port === port) ?? SERVERS[0];
|
||||
setSelectedServer(server);
|
||||
setServerInfoPromise(getServerInfo(port));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.callToolPanel}>
|
||||
<label>
|
||||
Server
|
||||
<select
|
||||
value={selectedServer.port}
|
||||
onChange={(e) => handleServerChange(Number(e.target.value))}
|
||||
>
|
||||
{SERVERS.map(({ name, port }) => (
|
||||
<option key={port} value={port}>
|
||||
{name} (:{port})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<ErrorBoundary>
|
||||
<Suspense fallback={<p className={styles.connecting}>Connecting to {serverUrl(selectedServer.port)}...</p>}>
|
||||
<ToolCallForm
|
||||
key={selectedServer.port}
|
||||
serverName={selectedServer.name}
|
||||
serverInfoPromise={serverInfoPromise}
|
||||
addToolCall={addToolCall}
|
||||
/>
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ToolCallForm renders inside Suspense - needs serverInfo for tool list
|
||||
interface ToolCallFormProps {
|
||||
serverName: string;
|
||||
serverInfoPromise: Promise<ServerInfo>;
|
||||
addToolCall: (serverName: string, info: ToolCallInfo) => void;
|
||||
}
|
||||
function ToolCallForm({ serverName, serverInfoPromise, addToolCall }: ToolCallFormProps) {
|
||||
const serverInfo = use(serverInfoPromise);
|
||||
const toolNames = Array.from(serverInfo.tools.keys());
|
||||
const [selectedTool, setSelectedTool] = useState(toolNames[0] ?? "");
|
||||
function CallToolPanel({ serversPromise, addToolCall }: CallToolPanelProps) {
|
||||
const [selectedServer, setSelectedServer] = useState<ServerInfo | null>(null);
|
||||
const [selectedTool, setSelectedTool] = useState("");
|
||||
const [inputJson, setInputJson] = useState("{}");
|
||||
|
||||
const toolNames = selectedServer ? Array.from(selectedServer.tools.keys()) : [];
|
||||
|
||||
const isValidJson = useMemo(() => {
|
||||
try {
|
||||
JSON.parse(inputJson);
|
||||
|
|
@ -125,49 +46,104 @@ function ToolCallForm({ serverName, serverInfoPromise, addToolCall }: ToolCallFo
|
|||
}
|
||||
}, [inputJson]);
|
||||
|
||||
const handleServerSelect = (server: ServerInfo) => {
|
||||
setSelectedServer(server);
|
||||
const [firstTool] = server.tools.keys();
|
||||
setSelectedTool(firstTool ?? "");
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
const toolCallInfo = callTool(serverInfo, selectedTool, JSON.parse(inputJson));
|
||||
addToolCall(serverName, toolCallInfo);
|
||||
if (!selectedServer) return;
|
||||
const toolCallInfo = callTool(selectedServer, selectedTool, JSON.parse(inputJson));
|
||||
addToolCall(toolCallInfo);
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
|
||||
<label>
|
||||
Tool
|
||||
<select
|
||||
value={selectedTool}
|
||||
onChange={(e) => setSelectedTool(e.target.value)}
|
||||
>
|
||||
{toolNames.map((name) => (
|
||||
<option key={name} value={name}>{name}</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
Input
|
||||
<textarea
|
||||
aria-invalid={!isValidJson}
|
||||
value={inputJson}
|
||||
onChange={(e) => setInputJson(e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<button type="submit" disabled={!selectedTool || !isValidJson}>
|
||||
Call Tool
|
||||
</button>
|
||||
</form>
|
||||
<div className={styles.callToolPanel}>
|
||||
<form onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
|
||||
<label>
|
||||
Server
|
||||
<Suspense fallback={<select disabled><option>Loading...</option></select>}>
|
||||
<ServerSelect serversPromise={serversPromise} onSelect={handleServerSelect} />
|
||||
</Suspense>
|
||||
</label>
|
||||
<label>
|
||||
Tool
|
||||
<select
|
||||
className={styles.toolSelect}
|
||||
value={selectedTool}
|
||||
onChange={(e) => setSelectedTool(e.target.value)}
|
||||
>
|
||||
{selectedServer && toolNames.map((name) => (
|
||||
<option key={name} value={name}>{name}</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
Input
|
||||
<textarea
|
||||
className={styles.toolInput}
|
||||
aria-invalid={!isValidJson}
|
||||
value={inputJson}
|
||||
onChange={(e) => setInputJson(e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<button type="submit" disabled={!selectedTool || !isValidJson}>
|
||||
Call Tool
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ServerSelect calls use() and renders the server <select>
|
||||
interface ServerSelectProps {
|
||||
serversPromise: Promise<ServerInfo[]>;
|
||||
onSelect: (server: ServerInfo) => void;
|
||||
}
|
||||
function ServerSelect({ serversPromise, onSelect }: ServerSelectProps) {
|
||||
const servers = use(serversPromise);
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (servers.length > selectedIndex) {
|
||||
onSelect(servers[selectedIndex]);
|
||||
}
|
||||
}, [servers]);
|
||||
|
||||
if (servers.length === 0) {
|
||||
return <select disabled><option>No servers configured</option></select>;
|
||||
}
|
||||
|
||||
return (
|
||||
<select
|
||||
value={selectedIndex}
|
||||
onChange={(e) => {
|
||||
const newIndex = Number(e.target.value);
|
||||
setSelectedIndex(newIndex);
|
||||
onSelect(servers[newIndex]);
|
||||
}}
|
||||
>
|
||||
{servers.map((server, i) => (
|
||||
<option key={i} value={i}>{server.name}</option>
|
||||
))}
|
||||
</select>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
interface ToolCallInfoPanelProps {
|
||||
serverName: string;
|
||||
toolCallInfo: ToolCallInfo;
|
||||
}
|
||||
function ToolCallInfoPanel({ serverName, toolCallInfo }: ToolCallInfoPanelProps) {
|
||||
function ToolCallInfoPanel({ toolCallInfo }: ToolCallInfoPanelProps) {
|
||||
return (
|
||||
<div className={styles.toolCallInfoPanel}>
|
||||
<div className={styles.inputInfoPanel}>
|
||||
<h2 className={styles.toolName}>{serverName}:{toolCallInfo.tool.name}</h2>
|
||||
<h2>
|
||||
<span>{toolCallInfo.serverInfo.name}</span>
|
||||
<span className={styles.toolName}>{toolCallInfo.tool.name}</span>
|
||||
</h2>
|
||||
<JsonBlock value={toolCallInfo.input} />
|
||||
</div>
|
||||
<div className={styles.outputInfoPanel}>
|
||||
|
|
@ -264,8 +240,16 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|||
}
|
||||
|
||||
|
||||
async function connectToAllServers(): Promise<ServerInfo[]> {
|
||||
const serverUrlsResponse = await fetch("/api/servers");
|
||||
const serverUrls = (await serverUrlsResponse.json()) as string[];
|
||||
return Promise.all(serverUrls.map((url) => connectToServer(new URL(url))));
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<Host />
|
||||
<ErrorBoundary>
|
||||
<Host serversPromise={connectToAllServers()} />
|
||||
</ErrorBoundary>
|
||||
</StrictMode>,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ const DIST_DIR = path.join(import.meta.dirname, "dist");
|
|||
|
||||
|
||||
const server = new McpServer({
|
||||
name: "MCP App Server",
|
||||
name: "Basic MCP App Server (React-based)",
|
||||
version: "1.0.0",
|
||||
});
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ app.post("/mcp", async (req: Request, res: Response) => {
|
|||
}
|
||||
});
|
||||
|
||||
const httpServer = app.listen(PORT, err => {
|
||||
const httpServer = app.listen(PORT, (err) => {
|
||||
if (err) {
|
||||
console.error("Error starting server:", err);
|
||||
process.exit(1);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ const DIST_DIR = path.join(import.meta.dirname, "dist");
|
|||
|
||||
|
||||
const server = new McpServer({
|
||||
name: "MCP App Server",
|
||||
name: "Basic MCP App Server (Vanilla JS)",
|
||||
version: "1.0.0",
|
||||
});
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ app.post("/mcp", async (req: Request, res: Response) => {
|
|||
}
|
||||
});
|
||||
|
||||
const httpServer = app.listen(PORT, err => {
|
||||
const httpServer = app.listen(PORT, (err) => {
|
||||
if (err) {
|
||||
console.error("Error starting server:", err);
|
||||
process.exit(1);
|
||||
|
|
|
|||
120
examples/run-all.ts
Normal file
120
examples/run-all.ts
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/env bun
|
||||
/**
|
||||
* Orchestration script for running all example servers.
|
||||
*
|
||||
* Usage:
|
||||
* bun examples/run-all.ts start - Build and start all examples
|
||||
* bun examples/run-all.ts dev - Run all examples in dev/watch mode
|
||||
* bun examples/run-all.ts build - Build all examples
|
||||
*/
|
||||
|
||||
import { readdirSync, statSync, existsSync } from "fs";
|
||||
import { spawn, type ChildProcess } from "child_process";
|
||||
|
||||
const BASE_PORT = 3101;
|
||||
const BASIC_HOST = "basic-host";
|
||||
|
||||
// Find all example directories except basic-host that have a package.json,
|
||||
// assign ports, and build URL list
|
||||
const servers = readdirSync("examples")
|
||||
.filter(
|
||||
(d) =>
|
||||
d !== BASIC_HOST &&
|
||||
statSync(`examples/${d}`).isDirectory() &&
|
||||
existsSync(`examples/${d}/package.json`),
|
||||
)
|
||||
.sort() // Sort for consistent port assignment
|
||||
.map((dir, i) => ({
|
||||
dir,
|
||||
port: BASE_PORT + i,
|
||||
url: `http://localhost:${BASE_PORT + i}/mcp`,
|
||||
}));
|
||||
|
||||
const COMMANDS = ["start", "dev", "build"];
|
||||
|
||||
const command = process.argv[2];
|
||||
|
||||
if (!command || !COMMANDS.includes(command)) {
|
||||
console.error(`Usage: bun examples/run-all.ts <${COMMANDS.join("|")}>`);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const processes: ChildProcess[] = [];
|
||||
|
||||
// Handle cleanup on exit
|
||||
function cleanup() {
|
||||
for (const proc of processes) {
|
||||
proc.kill();
|
||||
}
|
||||
}
|
||||
process.on("SIGINT", cleanup);
|
||||
process.on("SIGTERM", cleanup);
|
||||
|
||||
// Spawn a process and track it
|
||||
function spawnProcess(
|
||||
cmd: string,
|
||||
args: string[],
|
||||
env: Record<string, string> = {},
|
||||
prefix: string,
|
||||
): ChildProcess {
|
||||
const proc = spawn(cmd, args, {
|
||||
env: { ...process.env, ...env },
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
proc.stdout?.on("data", (data) => {
|
||||
const lines = data.toString().trim().split("\n");
|
||||
for (const line of lines) {
|
||||
console.log(`[${prefix}] ${line}`);
|
||||
}
|
||||
});
|
||||
|
||||
proc.stderr?.on("data", (data) => {
|
||||
const lines = data.toString().trim().split("\n");
|
||||
for (const line of lines) {
|
||||
console.error(`[${prefix}] ${line}`);
|
||||
}
|
||||
});
|
||||
|
||||
proc.on("exit", (code) => {
|
||||
if (code !== 0 && code !== null) {
|
||||
console.error(`[${prefix}] exited with code ${code}`);
|
||||
}
|
||||
});
|
||||
|
||||
processes.push(proc);
|
||||
return proc;
|
||||
}
|
||||
|
||||
// Build the SERVERS environment variable (JSON array of URLs)
|
||||
const serversEnv = JSON.stringify(servers.map((s) => s.url));
|
||||
|
||||
console.log(`Running command: ${command}`);
|
||||
console.log(
|
||||
`Server examples: ${servers.map((s) => `${s.dir}:${s.port}`).join(", ")}`,
|
||||
);
|
||||
console.log("");
|
||||
|
||||
// If dev mode, also run the main library watcher
|
||||
if (command === "dev") {
|
||||
spawnProcess("npm", ["run", "watch"], {}, "lib");
|
||||
}
|
||||
|
||||
// Run each server example
|
||||
for (const { dir, port } of servers) {
|
||||
spawnProcess(
|
||||
"npm",
|
||||
["run", "--workspace", `examples/${dir}`, command],
|
||||
{ PORT: String(port) },
|
||||
dir,
|
||||
);
|
||||
}
|
||||
|
||||
// Run basic-host with the SERVERS env var
|
||||
spawnProcess(
|
||||
"npm",
|
||||
["run", "--workspace", `examples/${BASIC_HOST}`, command],
|
||||
{ SERVERS: serversEnv },
|
||||
BASIC_HOST,
|
||||
);
|
||||
18
package.json
18
package.json
|
|
@ -31,22 +31,10 @@
|
|||
"prepack": "npm run build",
|
||||
"build:all": "npm run build && npm run examples:build",
|
||||
"test": "bun test",
|
||||
"examples:build": "find examples -maxdepth 1 -mindepth 1 -type d -exec printf '%s\\0' 'npm run --workspace={} build' ';' | xargs -0 concurrently --kill-others-on-fail",
|
||||
"examples:start": "NODE_ENV=development npm run build && concurrently 'npm run examples:start:basic-host' 'npm run examples:start:basic-server-react' 'npm run examples:start:basic-server-vanillajs' 'npm run examples:start:budget-allocator-server' 'npm run examples:start:cohort-heatmap-server' 'npm run examples:start:customer-segmentation-server' 'npm run examples:start:scenario-modeler-server' 'npm run examples:start:system-monitor-server' 'npm run examples:start:threejs-server'",
|
||||
"examples:start:basic-host": "npm run --workspace=examples/basic-host start",
|
||||
"examples:start:basic-server-react": "PORT=3101 npm run --workspace=examples/basic-server-react start",
|
||||
"examples:start:basic-server-vanillajs": "PORT=3102 npm run --workspace=examples/basic-server-vanillajs start",
|
||||
"examples:start:budget-allocator-server": "PORT=3103 npm run --workspace=examples/budget-allocator-server start",
|
||||
"examples:start:cohort-heatmap-server": "PORT=3104 npm run --workspace=examples/cohort-heatmap-server start",
|
||||
"examples:start:customer-segmentation-server": "PORT=3105 npm run --workspace=examples/customer-segmentation-server start",
|
||||
"examples:start:scenario-modeler-server": "PORT=3106 npm run --workspace=examples/scenario-modeler-server start",
|
||||
"examples:start:system-monitor-server": "PORT=3107 npm run --workspace=examples/system-monitor-server start",
|
||||
"examples:start:threejs-server": "PORT=3109 npm run --workspace=examples/threejs-server start",
|
||||
"examples:build": "bun examples/run-all.ts build",
|
||||
"examples:start": "NODE_ENV=development npm run build && bun examples/run-all.ts start",
|
||||
"examples:dev": "NODE_ENV=development bun examples/run-all.ts dev",
|
||||
"watch": "nodemon --watch src --ext ts,tsx --exec 'bun build.bun.ts'",
|
||||
"examples:dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run examples:dev:basic-host' 'npm run examples:dev:basic-server-react'",
|
||||
"examples:dev:basic-host": "npm run --workspace=examples/basic-host dev",
|
||||
"examples:dev:basic-server-react": "npm run --workspace=examples/basic-server-react dev",
|
||||
"examples:dev:basic-server-vanillajs": "npm run --workspace=examples/basic-server-vanillajs dev",
|
||||
"prepare": "npm run build && husky",
|
||||
"docs": "typedoc",
|
||||
"docs:watch": "typedoc --watch",
|
||||
|
|
|
|||
Loading…
Reference in a new issue