made tiny updates

This commit is contained in:
SinachPat
2026-05-03 20:34:18 +01:00
parent 4dca0f1bac
commit 3f029e15c2
30 changed files with 3463 additions and 357 deletions
+88 -28
View File
@@ -3,41 +3,54 @@
// ── Originmain CLI ───────────────────────────────────────────────────────────
// Usage:
// npx @originmain/cli dev --target http://localhost:3000 [--port 4170]
// [--index-port 4171] [--no-index]
//
// Starts a reverse proxy that enables live React component inspection
// in Originmain artboards. See RENDERING-ARCHITECTURE.md for details.
// Starts a reverse proxy + optional AST indexer for live React component
// inspection in Originmain artboards. See SOURCE-AWARE-CANVAS.md for details.
import { parseArgs } from 'node:util';
import { startProxy } from './proxy.js';
import { parseArgs } from 'node:util';
import { resolve } from 'node:path';
import { startProxy } from './proxy.js';
import { Indexer } from './indexer.js';
import { startIndexServer } from './index-server.js';
import { detectProjectMeta } from './detect-framework.js';
const DEFAULT_PORT = 4170;
const DEFAULT_PORT = 4170;
const DEFAULT_INDEX_PORT = 4171;
function printUsage(): void {
console.log(`
\x1b[36m\x1b[1mOriginmain CLI\x1b[0m
Usage:
originmain dev --target <url> [--port <number>]
originmain dev --target <url> [options]
Options:
--target, -t Target dev server URL (required)
Example: http://localhost:3000
--port, -p Proxy listen port (default: ${DEFAULT_PORT})
--help, -h Show this help
--target, -t Target dev server URL (required)
Example: http://localhost:3000
--port, -p Proxy listen port (default: ${DEFAULT_PORT})
--index-port AST indexer API port (default: ${DEFAULT_INDEX_PORT})
--no-index Disable the AST indexer (Props/Code tabs degraded)
--help, -h Show this help
Example:
Environment variables:
ORIGINMAIN_BRIDGE_URL Agent Bridge URL (default: http://localhost:4172)
Examples:
npx @originmain/cli dev --target http://localhost:3000
npx @originmain/cli dev --target http://localhost:3000 --no-index
`);
}
function main(): void {
// Parse arguments
async function main(): Promise<void> {
const { values, positionals } = parseArgs({
args: process.argv.slice(2),
options: {
target: { type: 'string', short: 't' },
port: { type: 'string', short: 'p' },
help: { type: 'boolean', short: 'h' },
target: { type: 'string', short: 't' },
port: { type: 'string', short: 'p' },
'index-port': { type: 'string' },
'no-index': { type: 'boolean' },
help: { type: 'boolean', short: 'h' },
},
allowPositionals: true,
strict: false,
@@ -47,7 +60,6 @@ function main(): void {
if (values.help || !command) {
printUsage();
// --help is a success; missing command is a usage error.
process.exit(values.help ? 0 : 1);
}
@@ -56,18 +68,16 @@ function main(): void {
process.exit(1);
}
// Validate --target
// ── Validate --target ─────────────────────────────────────────────────────
const target = values.target;
if (!target || typeof target !== 'string') {
console.error(' Error: --target is required.\n Example: originmain dev --target http://localhost:3000');
process.exit(1);
}
// Validate target URL
let targetUrl: URL;
try {
targetUrl = new URL(target);
} catch {
try { targetUrl = new URL(target); }
catch {
console.error(` Error: Invalid target URL: ${target}`);
process.exit(1);
}
@@ -77,20 +87,67 @@ function main(): void {
process.exit(1);
}
// Parse port
// ── Parse ports ───────────────────────────────────────────────────────────
const port = values.port ? parseInt(values.port as string, 10) : DEFAULT_PORT;
if (Number.isNaN(port) || port < 1 || port > 65535) {
console.error(` Error: Invalid port: ${values.port}`);
process.exit(1);
}
// Start proxy
const proxy = startProxy({ target, port });
const indexPortRaw = values['index-port'] as string | undefined;
const indexPort = indexPortRaw ? parseInt(indexPortRaw, 10) : DEFAULT_INDEX_PORT;
if (Number.isNaN(indexPort) || indexPort < 1 || indexPort > 65535) {
console.error(` Error: Invalid index port: ${indexPortRaw}`);
process.exit(1);
}
// Graceful shutdown
const noIndex = values['no-index'] === true;
// ── Agent Bridge URL ──────────────────────────────────────────────────────
let bridgeUrl = process.env['ORIGINMAIN_BRIDGE_URL'];
if (!bridgeUrl) {
// Try ~/.originmain/config.json
try {
const homeDir = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '';
const cfgPath = resolve(homeDir, '.originmain', 'config.json');
const { readFileSync } = await import('node:fs');
const cfg = JSON.parse(readFileSync(cfgPath, 'utf-8')) as Record<string, unknown>;
if (typeof cfg['bridgeUrl'] === 'string') bridgeUrl = cfg['bridgeUrl'];
} catch { /* config not present */ }
if (!bridgeUrl) {
bridgeUrl = 'http://localhost:4172';
console.log(` \x1b[2mUsing default Agent Bridge URL: ${bridgeUrl}\x1b[0m`);
}
}
// ── Start AST indexer (unless --no-index) ─────────────────────────────────
const projectRoot = process.cwd();
let indexServer: { close: () => void } | null = null;
if (!noIndex) {
const projectMeta = await detectProjectMeta(projectRoot);
const indexer = new Indexer(projectRoot);
// Start watching in background (non-blocking)
indexer.watch().catch((err: Error) => {
console.error(`[originmain indexer] Watch error: ${err.message}`);
});
indexServer = startIndexServer({ indexer, projectMeta, projectRoot, port: indexPort });
} else {
console.log(' \x1b[2mAST indexer disabled (--no-index)\x1b[0m');
}
// ── Start the reverse proxy ───────────────────────────────────────────────
const indexUrl = noIndex ? null : `http://localhost:${indexPort}`;
const proxy = startProxy({ target, port, indexUrl });
// ── Graceful shutdown ─────────────────────────────────────────────────────
function shutdown(): void {
console.log('\n Shutting down proxy...');
console.log('\n Shutting down...');
proxy.close();
indexServer?.close();
process.exit(0);
}
@@ -98,4 +155,7 @@ function main(): void {
process.on('SIGTERM', shutdown);
}
main();
main().catch((err: unknown) => {
console.error(' Fatal error:', err);
process.exit(1);
});