@voltx/cli 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +54 -22
  2. package/dist/build.d.mts +4 -3
  3. package/dist/build.d.ts +4 -3
  4. package/dist/build.js +56 -27
  5. package/dist/build.mjs +1 -2
  6. package/dist/chunk-2LHDOMF2.mjs +680 -0
  7. package/dist/chunk-5DVBIJXU.mjs +84 -0
  8. package/dist/chunk-65PVXS4D.mjs +894 -0
  9. package/dist/chunk-7JVIEGSA.mjs +141 -0
  10. package/dist/chunk-A4NA4AJN.mjs +786 -0
  11. package/dist/chunk-AAAHANST.mjs +839 -0
  12. package/dist/chunk-AD3WMFZF.mjs +205 -0
  13. package/dist/chunk-CSSHLVYS.mjs +83 -0
  14. package/dist/chunk-CWOSNV5O.mjs +150 -0
  15. package/dist/chunk-EI6XBYKB.mjs +84 -0
  16. package/dist/chunk-FI2W4L4S.mjs +205 -0
  17. package/dist/chunk-G2INQCCJ.mjs +907 -0
  18. package/dist/chunk-H2DTIOEO.mjs +150 -0
  19. package/dist/chunk-IS2WTE3C.mjs +138 -0
  20. package/dist/chunk-JECCDBYI.mjs +730 -0
  21. package/dist/chunk-KX2MRJUO.mjs +795 -0
  22. package/dist/chunk-LTGMHAZS.mjs +147 -0
  23. package/dist/chunk-OPO6RUFP.mjs +698 -0
  24. package/dist/chunk-PWQSKYAM.mjs +682 -0
  25. package/dist/chunk-Q5XCFN7L.mjs +1026 -0
  26. package/dist/chunk-QSU6FZC7.mjs +497 -0
  27. package/dist/chunk-RYWRFHEC.mjs +83 -0
  28. package/dist/chunk-SU4Q3PTH.mjs +201 -0
  29. package/dist/chunk-TFVNHM7S.mjs +1028 -0
  30. package/dist/chunk-UXI3QSDN.mjs +121 -0
  31. package/dist/chunk-VD3CNPNP.mjs +123 -0
  32. package/dist/chunk-X6VOAPRJ.mjs +756 -0
  33. package/dist/cli.js +935 -308
  34. package/dist/cli.mjs +7 -6
  35. package/dist/create.d.mts +1 -0
  36. package/dist/create.d.ts +1 -0
  37. package/dist/create.js +726 -192
  38. package/dist/create.mjs +1 -2
  39. package/dist/dev.d.mts +6 -4
  40. package/dist/dev.d.ts +6 -4
  41. package/dist/dev.js +119 -46
  42. package/dist/dev.mjs +1 -2
  43. package/dist/generate.js +13 -13
  44. package/dist/generate.mjs +1 -2
  45. package/dist/index.js +922 -296
  46. package/dist/index.mjs +5 -6
  47. package/dist/start.js +7 -17
  48. package/dist/start.mjs +1 -2
  49. package/dist/welcome.mjs +0 -1
  50. package/package.json +11 -3
package/dist/create.mjs CHANGED
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createProject
4
- } from "./chunk-P5FSO2UH.mjs";
4
+ } from "./chunk-TFVNHM7S.mjs";
5
5
  import "./chunk-IV352HZA.mjs";
6
- import "./chunk-Y6FXYEAI.mjs";
7
6
  export {
8
7
  createProject
9
8
  };
package/dist/dev.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  interface DevOptions {
2
2
  /** Port override (reads from voltx.config.ts or env if not set) */
3
3
  port?: number;
4
- /** Entry file (default: src/index.ts) */
4
+ /** Entry file (default: server.ts) */
5
5
  entry?: string;
6
6
  /** Extra directories to watch */
7
7
  watch?: string[];
@@ -9,10 +9,12 @@ interface DevOptions {
9
9
  clearScreen?: boolean;
10
10
  }
11
11
  /**
12
- * Start the VoltX dev server with hot reload.
12
+ * Start the VoltX dev server.
13
13
  *
14
- * Spawns `tsx watch` on the app entry point. tsx handles TypeScript
15
- * compilation and automatic restarts when files change.
14
+ * Detects whether the project is full-stack (has vite.config.ts or server.ts).
15
+ * - If yes: starts Vite with @hono/vite-dev-server plugin — one process,
16
+ * one port, frontend HMR + backend API routes together.
17
+ * - If no: spawns tsx watch for fast API-only development.
16
18
  */
17
19
  declare function runDev(options?: DevOptions): Promise<void>;
18
20
 
package/dist/dev.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  interface DevOptions {
2
2
  /** Port override (reads from voltx.config.ts or env if not set) */
3
3
  port?: number;
4
- /** Entry file (default: src/index.ts) */
4
+ /** Entry file (default: server.ts) */
5
5
  entry?: string;
6
6
  /** Extra directories to watch */
7
7
  watch?: string[];
@@ -9,10 +9,12 @@ interface DevOptions {
9
9
  clearScreen?: boolean;
10
10
  }
11
11
  /**
12
- * Start the VoltX dev server with hot reload.
12
+ * Start the VoltX dev server.
13
13
  *
14
- * Spawns `tsx watch` on the app entry point. tsx handles TypeScript
15
- * compilation and automatic restarts when files change.
14
+ * Detects whether the project is full-stack (has vite.config.ts or server.ts).
15
+ * - If yes: starts Vite with @hono/vite-dev-server plugin — one process,
16
+ * one port, frontend HMR + backend API routes together.
17
+ * - If no: spawns tsx watch for fast API-only development.
16
18
  */
17
19
  declare function runDev(options?: DevOptions): Promise<void>;
18
20
 
package/dist/dev.js CHANGED
@@ -26,6 +26,7 @@ module.exports = __toCommonJS(dev_exports);
26
26
  var import_node_child_process = require("child_process");
27
27
  var import_node_path = require("path");
28
28
  var import_node_fs = require("fs");
29
+ var import_core = require("@voltx/core");
29
30
  async function runDev(options = {}) {
30
31
  const cwd = process.cwd();
31
32
  const {
@@ -34,7 +35,7 @@ async function runDev(options = {}) {
34
35
  clearScreen = true
35
36
  } = options;
36
37
  if (!entry) {
37
- console.error("[voltx] Could not find entry point. Expected src/index.ts or src/index.js");
38
+ console.error("[voltx] Could not find entry point. Expected server.ts or src/index.ts");
38
39
  process.exit(1);
39
40
  }
40
41
  const entryPath = (0, import_node_path.resolve)(cwd, entry);
@@ -42,56 +43,124 @@ async function runDev(options = {}) {
42
43
  console.error(`[voltx] Entry file not found: ${entry}`);
43
44
  process.exit(1);
44
45
  }
45
- const envFile = (0, import_node_path.resolve)(cwd, ".env");
46
+ (0, import_core.loadEnv)("development", cwd);
47
+ const hasViteConfig = (0, import_node_fs.existsSync)((0, import_node_path.resolve)(cwd, "vite.config.ts"));
48
+ const hasServerEntry = (0, import_node_fs.existsSync)((0, import_node_path.resolve)(cwd, "server.ts"));
49
+ const isFullStack = hasViteConfig || hasServerEntry;
50
+ if (isFullStack) {
51
+ await startViteDevServer(cwd, port, entry, options);
52
+ } else {
53
+ await startTsxWatch(cwd, port, entry, options);
54
+ }
55
+ }
56
+ async function startViteDevServer(cwd, port, entry, options) {
57
+ const resolvedPort = port ?? (Number(process.env.PORT) || 3e3);
58
+ printDevBanner(entry, resolvedPort, true);
59
+ const userViteConfig = (0, import_node_path.resolve)(cwd, "vite.config.ts");
60
+ const hasUserViteConfig = (0, import_node_fs.existsSync)(userViteConfig);
61
+ let tempConfigPath = null;
62
+ if (!hasUserViteConfig) {
63
+ tempConfigPath = (0, import_node_path.resolve)(cwd, "vite.config.voltx.ts");
64
+ const viteConfigContent = generateViteConfig(entry, resolvedPort);
65
+ (0, import_node_fs.writeFileSync)(tempConfigPath, viteConfigContent, "utf-8");
66
+ }
46
67
  const env = {
47
68
  ...process.env,
48
69
  NODE_ENV: "development"
49
70
  };
50
- if ((0, import_node_fs.existsSync)(envFile)) {
51
- const envContent = (0, import_node_fs.readFileSync)(envFile, "utf-8");
52
- for (const line of envContent.split("\n")) {
53
- const trimmed = line.trim();
54
- if (!trimmed || trimmed.startsWith("#")) continue;
55
- const eqIdx = trimmed.indexOf("=");
56
- if (eqIdx === -1) continue;
57
- const key = trimmed.slice(0, eqIdx).trim();
58
- const value = trimmed.slice(eqIdx + 1).trim();
59
- env[key] = value;
71
+ if (port) {
72
+ env.PORT = String(port);
73
+ }
74
+ const viteBin = findBin(cwd, "vite");
75
+ const viteArgs = ["dev"];
76
+ if (tempConfigPath) {
77
+ viteArgs.push("--config", tempConfigPath);
78
+ }
79
+ viteArgs.push("--port", String(resolvedPort));
80
+ let child;
81
+ if (viteBin) {
82
+ child = (0, import_node_child_process.spawn)(viteBin, viteArgs, { cwd, env, stdio: "inherit" });
83
+ } else {
84
+ child = (0, import_node_child_process.spawn)("npx", ["vite", ...viteArgs], { cwd, env, stdio: "inherit" });
85
+ }
86
+ const cleanup = () => {
87
+ if (tempConfigPath && (0, import_node_fs.existsSync)(tempConfigPath)) {
88
+ try {
89
+ (0, import_node_fs.unlinkSync)(tempConfigPath);
90
+ } catch {
91
+ }
60
92
  }
93
+ };
94
+ const signals = ["SIGINT", "SIGTERM"];
95
+ for (const signal of signals) {
96
+ process.on(signal, () => {
97
+ cleanup();
98
+ child.kill(signal);
99
+ });
61
100
  }
101
+ child.on("error", (err) => {
102
+ cleanup();
103
+ if (err.code === "ENOENT") {
104
+ console.error("[voltx] vite not found. Install it with: npm install -D vite @hono/vite-dev-server");
105
+ } else {
106
+ console.error("[voltx] Dev server error:", err.message);
107
+ }
108
+ process.exit(1);
109
+ });
110
+ child.on("exit", (code) => {
111
+ cleanup();
112
+ process.exit(code ?? 0);
113
+ });
114
+ }
115
+ function generateViteConfig(entry, port) {
116
+ return `// Auto-generated by VoltX \u2014 do not commit this file
117
+ import { defineConfig } from "vite";
118
+ import devServer from "@hono/vite-dev-server";
119
+
120
+ export default defineConfig({
121
+ server: {
122
+ port: ${port},
123
+ },
124
+ plugins: [
125
+ devServer({
126
+ entry: "${entry}",
127
+ exclude: [
128
+ /.*\\.tsx?($|\\?)/,
129
+ /.*\\.(s?css|less)($|\\?)/,
130
+ /.*\\.(svg|png|jpg|jpeg|gif|webp|ico)($|\\?)/,
131
+ /^\\/@.+$/,
132
+ /^\\/favicon\\.svg$/,
133
+ /^\\/node_modules\\/.*/,
134
+ /^\\/src\\/.*/,
135
+ ],
136
+ injectClientScript: false,
137
+ }),
138
+ ],
139
+ });
140
+ `;
141
+ }
142
+ async function startTsxWatch(cwd, port, entry, options) {
143
+ const resolvedPort = port ?? (Number(process.env.PORT) || 3e3);
144
+ printDevBanner(entry, resolvedPort, false);
145
+ const env = {
146
+ ...process.env,
147
+ NODE_ENV: "development"
148
+ };
62
149
  if (port) {
63
150
  env.PORT = String(port);
64
151
  }
65
- printDevBanner(entry, port);
66
152
  const tsxArgs = ["watch"];
67
- if (clearScreen) {
153
+ if (options.clearScreen ?? true) {
68
154
  tsxArgs.push("--clear-screen=false");
69
155
  }
70
- const watchDirs = [
71
- "src/routes",
72
- "src/agents",
73
- "src/tools",
74
- "src/jobs",
75
- "src/lib",
76
- "voltx.config.ts",
77
- ...options.watch ?? []
78
- ];
79
156
  tsxArgs.push("--ignore=node_modules", "--ignore=dist", "--ignore=.turbo");
80
157
  tsxArgs.push(entry);
81
- const tsxBin = findTsxBin(cwd);
158
+ const tsxBin = findBin(cwd, "tsx");
82
159
  let child;
83
160
  if (tsxBin) {
84
- child = (0, import_node_child_process.spawn)(tsxBin, tsxArgs, {
85
- cwd,
86
- env,
87
- stdio: "inherit"
88
- });
161
+ child = (0, import_node_child_process.spawn)(tsxBin, tsxArgs, { cwd, env, stdio: "inherit" });
89
162
  } else {
90
- child = (0, import_node_child_process.spawn)("npx", ["tsx", ...tsxArgs], {
91
- cwd,
92
- env,
93
- stdio: "inherit"
94
- });
163
+ child = (0, import_node_child_process.spawn)("npx", ["tsx", ...tsxArgs], { cwd, env, stdio: "inherit" });
95
164
  }
96
165
  const signals = ["SIGINT", "SIGTERM"];
97
166
  for (const signal of signals) {
@@ -102,7 +171,6 @@ async function runDev(options = {}) {
102
171
  child.on("error", (err) => {
103
172
  if (err.code === "ENOENT") {
104
173
  console.error("[voltx] tsx not found. Install it with: npm install -D tsx");
105
- console.error("[voltx] Or run your app directly: npx tsx watch src/index.ts");
106
174
  } else {
107
175
  console.error("[voltx] Dev server error:", err.message);
108
176
  }
@@ -114,6 +182,8 @@ async function runDev(options = {}) {
114
182
  }
115
183
  function findEntryPoint(cwd) {
116
184
  const candidates = [
185
+ "server.ts",
186
+ "server.js",
117
187
  "src/index.ts",
118
188
  "src/index.js",
119
189
  "src/index.mts",
@@ -129,24 +199,27 @@ function findEntryPoint(cwd) {
129
199
  }
130
200
  return null;
131
201
  }
132
- function findTsxBin(cwd) {
133
- const localBin = (0, import_node_path.join)(cwd, "node_modules", ".bin", "tsx");
134
- if ((0, import_node_fs.existsSync)(localBin)) return localBin;
135
- const parentBin = (0, import_node_path.join)(cwd, "..", "node_modules", ".bin", "tsx");
136
- if ((0, import_node_fs.existsSync)(parentBin)) return parentBin;
137
- const rootBin = (0, import_node_path.join)(cwd, "..", "..", "node_modules", ".bin", "tsx");
138
- if ((0, import_node_fs.existsSync)(rootBin)) return rootBin;
202
+ function findBin(cwd, name) {
203
+ const paths = [
204
+ (0, import_node_path.join)(cwd, "node_modules", ".bin", name),
205
+ (0, import_node_path.join)(cwd, "..", "node_modules", ".bin", name),
206
+ (0, import_node_path.join)(cwd, "..", "..", "node_modules", ".bin", name)
207
+ ];
208
+ for (const p of paths) {
209
+ if ((0, import_node_fs.existsSync)(p)) return p;
210
+ }
139
211
  return null;
140
212
  }
141
- function printDevBanner(entry, port) {
213
+ function printDevBanner(entry, port, fullStack) {
142
214
  console.log("");
143
215
  console.log(" \u26A1 VoltX Dev Server");
144
216
  console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
145
217
  console.log(` Entry: ${entry}`);
146
- if (port) {
147
- console.log(` Port: ${port}`);
218
+ console.log(` Port: ${port}`);
219
+ console.log(` Mode: ${fullStack ? "full-stack (Vite + Hono)" : "API-only (tsx watch)"}`);
220
+ if (fullStack) {
221
+ console.log(` HMR: enabled (frontend + backend)`);
148
222
  }
149
- console.log(` Mode: development (hot reload)`);
150
223
  console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
151
224
  console.log("");
152
225
  }
package/dist/dev.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  runDev
3
- } from "./chunk-QND74HUW.mjs";
4
- import "./chunk-Y6FXYEAI.mjs";
3
+ } from "./chunk-AD3WMFZF.mjs";
5
4
  export {
6
5
  runDev
7
6
  };
package/dist/generate.js CHANGED
@@ -49,13 +49,13 @@ async function runGenerate(options) {
49
49
  }
50
50
  function generateRoute(cwd, name, method = "POST") {
51
51
  const routePath = name.startsWith("/") ? name.slice(1) : name;
52
- const filePath = (0, import_node_path.join)(cwd, "src", "routes", `${routePath}.ts`);
52
+ const filePath = (0, import_node_path.join)(cwd, "api", `${routePath}.ts`);
53
53
  if ((0, import_node_fs.existsSync)(filePath)) {
54
- console.error(`[voltx] Route already exists: src/routes/${routePath}.ts`);
54
+ console.error(`[voltx] Route already exists: api/${routePath}.ts`);
55
55
  process.exit(1);
56
56
  }
57
57
  const upperMethod = method.toUpperCase();
58
- const urlPath = "/" + routePath;
58
+ const urlPath = "/api/" + routePath;
59
59
  const content = `// ${upperMethod} ${urlPath}
60
60
  import type { Context } from "@voltx/server";
61
61
 
@@ -64,13 +64,13 @@ export async function ${upperMethod}(c: Context) {
64
64
  }
65
65
  `;
66
66
  writeFileSafe(filePath, content);
67
- console.log(` \u2713 Created route: src/routes/${routePath}.ts`);
67
+ console.log(` \u2713 Created route: api/${routePath}.ts`);
68
68
  console.log(` ${upperMethod} ${urlPath}`);
69
69
  }
70
70
  function generateAgent(cwd, name) {
71
- const filePath = (0, import_node_path.join)(cwd, "src", "agents", `${name}.ts`);
71
+ const filePath = (0, import_node_path.join)(cwd, "agents", `${name}.ts`);
72
72
  if ((0, import_node_fs.existsSync)(filePath)) {
73
- console.error(`[voltx] Agent already exists: src/agents/${name}.ts`);
73
+ console.error(`[voltx] Agent already exists: agents/${name}.ts`);
74
74
  process.exit(1);
75
75
  }
76
76
  const content = `// Agent: ${name}
@@ -92,12 +92,12 @@ export const ${toCamelCase(name)} = createAgent({
92
92
  });
93
93
  `;
94
94
  writeFileSafe(filePath, content);
95
- console.log(` \u2713 Created agent: src/agents/${name}.ts`);
95
+ console.log(` \u2713 Created agent: agents/${name}.ts`);
96
96
  }
97
97
  function generateTool(cwd, name) {
98
- const filePath = (0, import_node_path.join)(cwd, "src", "tools", `${name}.ts`);
98
+ const filePath = (0, import_node_path.join)(cwd, "tools", `${name}.ts`);
99
99
  if ((0, import_node_fs.existsSync)(filePath)) {
100
- console.error(`[voltx] Tool already exists: src/tools/${name}.ts`);
100
+ console.error(`[voltx] Tool already exists: tools/${name}.ts`);
101
101
  process.exit(1);
102
102
  }
103
103
  const content = `// Tool: ${name}
@@ -119,12 +119,12 @@ export const ${toCamelCase(name)}Tool = {
119
119
  };
120
120
  `;
121
121
  writeFileSafe(filePath, content);
122
- console.log(` \u2713 Created tool: src/tools/${name}.ts`);
122
+ console.log(` \u2713 Created tool: tools/${name}.ts`);
123
123
  }
124
124
  function generateJob(cwd, name) {
125
- const filePath = (0, import_node_path.join)(cwd, "src", "jobs", `${name}.ts`);
125
+ const filePath = (0, import_node_path.join)(cwd, "jobs", `${name}.ts`);
126
126
  if ((0, import_node_fs.existsSync)(filePath)) {
127
- console.error(`[voltx] Job already exists: src/jobs/${name}.ts`);
127
+ console.error(`[voltx] Job already exists: jobs/${name}.ts`);
128
128
  process.exit(1);
129
129
  }
130
130
  const content = `// Job: ${name}
@@ -149,7 +149,7 @@ export async function run(ctx: any, data?: Record<string, unknown>) {
149
149
  }
150
150
  `;
151
151
  writeFileSafe(filePath, content);
152
- console.log(` \u2713 Created job: src/jobs/${name}.ts`);
152
+ console.log(` \u2713 Created job: jobs/${name}.ts`);
153
153
  }
154
154
  function writeFileSafe(filePath, content) {
155
155
  const dir = (0, import_node_path.dirname)(filePath);
package/dist/generate.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  runGenerate
3
- } from "./chunk-HAFJKS2O.mjs";
4
- import "./chunk-Y6FXYEAI.mjs";
3
+ } from "./chunk-7JVIEGSA.mjs";
5
4
  export {
6
5
  runGenerate
7
6
  };