Skip to content

Commit df9c41a

Browse files
committed
testing npx build
1 parent d6bccd5 commit df9c41a

3 files changed

Lines changed: 643 additions & 5 deletions

File tree

cli.js

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#!/usr/bin/env node
2+
3+
import { spawn, spawnSync } from "child_process";
4+
import open from "open";
5+
import path from "path";
6+
import fs from "fs";
7+
import { fileURLToPath } from "url";
8+
import { select } from "@inquirer/prompts";
9+
10+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
11+
12+
const FRONTEND_PORT = 4173;
13+
const REST_PORT = 5000;
14+
15+
/* ---------------------------
16+
PRE-FLIGHT CHECKS
17+
---------------------------- */
18+
19+
function fail(msg) {
20+
console.error(`\n${msg}\n`);
21+
process.exit(1);
22+
}
23+
24+
function checkVerdi() {
25+
const res = spawnSync("verdi", ["--help"], { encoding: "utf-8" });
26+
27+
if (res.error) {
28+
fail('"verdi" not found. Is AiiDA installed and activated?');
29+
}
30+
}
31+
32+
function checkRestApiDeps() {
33+
const res = spawnSync(
34+
"python",
35+
["-c", "from aiida.restapi.run_api import run_api"],
36+
{ encoding: "utf-8" },
37+
);
38+
39+
if (res.status !== 0) {
40+
fail(
41+
"Missing AiiDA REST API dependencies.\n\nFix:\n pip install aiida-core[rest-api]",
42+
);
43+
}
44+
}
45+
46+
function checkFrontend() {
47+
const distPath = path.join(__dirname, "dist");
48+
49+
if (!fs.existsSync(distPath)) {
50+
fail('Frontend build missing. Expected "dist/" in package.');
51+
}
52+
}
53+
54+
/* ---------------------------
55+
PROFILE SELECTION
56+
---------------------------- */
57+
58+
function getProfiles() {
59+
const res = spawnSync("verdi", ["profile", "list"], {
60+
encoding: "utf-8",
61+
});
62+
63+
if (res.status !== 0) {
64+
fail("Failed to fetch AiiDA profiles");
65+
}
66+
67+
const lines = res.stdout.split("\n");
68+
69+
let active = null;
70+
71+
const profiles = lines
72+
.map((l) => l.trim())
73+
.filter((l) => l && !l.startsWith("Report"))
74+
.map((l) => {
75+
if (l.startsWith("*")) {
76+
active = l.replace(/^\*\s*/, "");
77+
return active;
78+
}
79+
return l.replace(/^\*\s*/, "");
80+
})
81+
.filter(Boolean);
82+
83+
return { profiles, active };
84+
}
85+
86+
async function selectProfile(profiles, active) {
87+
return await select({
88+
message: "Select AiiDA profile",
89+
choices: profiles.map((p) => ({
90+
name: p,
91+
value: p,
92+
description: p === active ? "active" : undefined,
93+
})),
94+
default: active,
95+
});
96+
}
97+
98+
/* ---------------------------
99+
STARTUP
100+
---------------------------- */
101+
102+
let restProc = null;
103+
let frontendProc = null;
104+
105+
function startRestApi(profile) {
106+
console.log(`Starting AiiDA REST API (profile: ${profile})...`);
107+
108+
const proc = spawn("verdi", ["-p", profile, "restapi", "--port", REST_PORT], {
109+
stdio: "inherit",
110+
});
111+
112+
proc.on("exit", (code) => {
113+
console.log(`\nREST API exited with code ${code}`);
114+
});
115+
116+
return proc;
117+
}
118+
119+
function startFrontend() {
120+
console.log("🌐 Starting frontend (Vite preview)...");
121+
122+
const viteBin = path.join(__dirname, "node_modules", ".bin", "vite");
123+
124+
const proc = spawn(viteBin, ["preview", "--port", FRONTEND_PORT], {
125+
cwd: __dirname,
126+
stdio: "inherit",
127+
});
128+
129+
proc.on("exit", (code) => {
130+
console.log(`\nFrontend exited with code ${code}`);
131+
});
132+
133+
return proc;
134+
}
135+
136+
/* ---------------------------
137+
MAIN
138+
---------------------------- */
139+
140+
async function main() {
141+
checkVerdi();
142+
checkRestApiDeps();
143+
checkFrontend();
144+
145+
const { profiles, active } = getProfiles();
146+
const selectedProfile = await selectProfile(profiles, active);
147+
148+
restProc = startRestApi(selectedProfile);
149+
frontendProc = startFrontend();
150+
151+
setTimeout(() => {
152+
const apiUrl = `http://localhost:${REST_PORT}/api/v4`;
153+
154+
const url =
155+
`http://localhost:${FRONTEND_PORT}/` +
156+
`?api_url=${encodeURIComponent(apiUrl)}`;
157+
158+
console.log("\nOpening browser...\n");
159+
open(url);
160+
}, 5000);
161+
162+
function shutdown() {
163+
console.log("\nShutting down...");
164+
165+
if (restProc) restProc.kill("SIGTERM");
166+
if (frontendProc) frontendProc.kill("SIGTERM");
167+
168+
process.exit(0);
169+
}
170+
171+
process.on("SIGINT", shutdown);
172+
process.on("SIGTERM", shutdown);
173+
}
174+
175+
main();

0 commit comments

Comments
 (0)