@voltx/cli 0.2.0 → 0.3.0

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 (45) hide show
  1. package/README.md +65 -0
  2. package/dist/build.d.mts +19 -0
  3. package/dist/build.d.ts +19 -0
  4. package/dist/build.js +145 -0
  5. package/dist/build.mjs +7 -0
  6. package/dist/chunk-AONHLE42.mjs +141 -0
  7. package/dist/chunk-BIE3F5AW.mjs +261 -0
  8. package/dist/chunk-BLBAHJXR.mjs +239 -0
  9. package/dist/chunk-IGBR4TFT.mjs +351 -0
  10. package/dist/chunk-IV352HZA.mjs +107 -0
  11. package/dist/chunk-KFHPTRKZ.mjs +405 -0
  12. package/dist/chunk-L3247M3A.mjs +81 -0
  13. package/dist/chunk-RN7BUALR.mjs +120 -0
  14. package/dist/chunk-SGL7RBD5.mjs +355 -0
  15. package/dist/chunk-TUZ3MHD4.mjs +355 -0
  16. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  17. package/dist/chunk-ZA7EJWJI.mjs +221 -0
  18. package/dist/chunk-ZB2F3WTS.mjs +121 -0
  19. package/dist/chunk-ZLIPYI22.mjs +350 -0
  20. package/dist/cli.js +945 -59
  21. package/dist/cli.mjs +123 -23
  22. package/dist/create.d.mts +1 -0
  23. package/dist/create.d.ts +1 -0
  24. package/dist/create.js +308 -36
  25. package/dist/create.mjs +3 -2
  26. package/dist/dev.d.mts +19 -0
  27. package/dist/dev.d.ts +19 -0
  28. package/dist/dev.js +144 -0
  29. package/dist/dev.mjs +7 -0
  30. package/dist/generate.d.mts +13 -0
  31. package/dist/generate.d.ts +13 -0
  32. package/dist/generate.js +165 -0
  33. package/dist/generate.mjs +7 -0
  34. package/dist/index.d.mts +5 -1
  35. package/dist/index.d.ts +5 -1
  36. package/dist/index.js +770 -39
  37. package/dist/index.mjs +21 -4
  38. package/dist/start.d.mts +16 -0
  39. package/dist/start.d.ts +16 -0
  40. package/dist/start.js +105 -0
  41. package/dist/start.mjs +7 -0
  42. package/dist/welcome.js +1 -1
  43. package/dist/welcome.mjs +2 -1
  44. package/package.json +24 -22
  45. package/LICENSE +0 -21
@@ -0,0 +1,121 @@
1
+ // src/build.ts
2
+ import { spawn } from "child_process";
3
+ import { resolve, join } from "path";
4
+ import { existsSync, mkdirSync } from "fs";
5
+ async function runBuild(options = {}) {
6
+ const cwd = process.cwd();
7
+ const {
8
+ entry = findEntryPoint(cwd),
9
+ outDir = "dist",
10
+ minify = true,
11
+ sourcemap = false
12
+ } = options;
13
+ if (!entry) {
14
+ console.error("[voltx] Could not find entry point. Expected src/index.ts");
15
+ process.exit(1);
16
+ }
17
+ const entryPath = resolve(cwd, entry);
18
+ if (!existsSync(entryPath)) {
19
+ console.error(`[voltx] Entry file not found: ${entry}`);
20
+ process.exit(1);
21
+ }
22
+ console.log("");
23
+ console.log(" \u26A1 VoltX Build");
24
+ 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");
25
+ console.log(` Entry: ${entry}`);
26
+ console.log(` Output: ${outDir}/`);
27
+ console.log(` Minify: ${minify}`);
28
+ 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");
29
+ console.log("");
30
+ mkdirSync(resolve(cwd, outDir), { recursive: true });
31
+ console.log(" [1/2] Building server...");
32
+ const tsupArgs = [
33
+ entry,
34
+ "--format",
35
+ "esm",
36
+ "--out-dir",
37
+ outDir,
38
+ "--clean",
39
+ "--target",
40
+ "node20"
41
+ ];
42
+ if (minify) tsupArgs.push("--minify");
43
+ if (sourcemap) tsupArgs.push("--sourcemap");
44
+ tsupArgs.push("--no-splitting");
45
+ const tsupBin = findBin(cwd, "tsup");
46
+ await runCommand(
47
+ tsupBin ?? "npx",
48
+ tsupBin ? tsupArgs : ["tsup", ...tsupArgs],
49
+ cwd
50
+ );
51
+ console.log(" \u2713 Server built successfully");
52
+ const frontendDir = resolve(cwd, "src", "frontend");
53
+ const viteConfig = resolve(cwd, "vite.config.ts");
54
+ const hasFrontend = existsSync(frontendDir) || existsSync(viteConfig);
55
+ if (hasFrontend) {
56
+ console.log(" [2/2] Building frontend...");
57
+ const viteBin = findBin(cwd, "vite");
58
+ const viteArgs = ["build", "--outDir", join(outDir, "public")];
59
+ await runCommand(
60
+ viteBin ?? "npx",
61
+ viteBin ? viteArgs : ["vite", ...viteArgs],
62
+ cwd
63
+ );
64
+ console.log(" \u2713 Frontend built successfully");
65
+ } else {
66
+ console.log(" [2/2] No frontend found, skipping...");
67
+ }
68
+ console.log("");
69
+ console.log(" \u26A1 Build complete!");
70
+ console.log(` Run \`voltx start\` to start the production server.`);
71
+ console.log("");
72
+ }
73
+ function findEntryPoint(cwd) {
74
+ const candidates = [
75
+ "src/index.ts",
76
+ "src/index.js",
77
+ "src/index.mts",
78
+ "src/main.ts",
79
+ "src/main.js"
80
+ ];
81
+ for (const candidate of candidates) {
82
+ if (existsSync(join(cwd, candidate))) {
83
+ return candidate;
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+ function findBin(cwd, name) {
89
+ const paths = [
90
+ join(cwd, "node_modules", ".bin", name),
91
+ join(cwd, "..", "node_modules", ".bin", name),
92
+ join(cwd, "..", "..", "node_modules", ".bin", name)
93
+ ];
94
+ for (const p of paths) {
95
+ if (existsSync(p)) return p;
96
+ }
97
+ return null;
98
+ }
99
+ function runCommand(cmd, args, cwd) {
100
+ return new Promise((resolve2, reject) => {
101
+ const child = spawn(cmd, args, {
102
+ cwd,
103
+ stdio: "inherit",
104
+ env: { ...process.env, NODE_ENV: "production" }
105
+ });
106
+ child.on("error", (err) => {
107
+ if (err.code === "ENOENT") {
108
+ console.error(`[voltx] ${cmd} not found. Install it with: npm install -D ${cmd}`);
109
+ }
110
+ reject(err);
111
+ });
112
+ child.on("exit", (code) => {
113
+ if (code === 0) resolve2();
114
+ else reject(new Error(`${cmd} exited with code ${code}`));
115
+ });
116
+ });
117
+ }
118
+
119
+ export {
120
+ runBuild
121
+ };
@@ -0,0 +1,350 @@
1
+ import {
2
+ __require,
3
+ printWelcomeBanner
4
+ } from "./chunk-RH5Q7I3S.mjs";
5
+
6
+ // src/create.ts
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ async function createProject(options) {
10
+ const { name, template = "blank", auth = "none" } = options;
11
+ const targetDir = path.resolve(process.cwd(), name);
12
+ if (fs.existsSync(targetDir)) {
13
+ console.error(`[voltx] Directory "${name}" already exists.`);
14
+ process.exit(1);
15
+ }
16
+ fs.mkdirSync(targetDir, { recursive: true });
17
+ const templateDeps = {
18
+ blank: {
19
+ "@voltx/core": "^0.2.0",
20
+ "@voltx/server": "^0.2.0"
21
+ },
22
+ chatbot: {
23
+ "@voltx/core": "^0.2.0",
24
+ "@voltx/ai": "^0.2.0",
25
+ "@voltx/server": "^0.2.0",
26
+ "@voltx/memory": "^0.2.0"
27
+ },
28
+ "rag-app": {
29
+ "@voltx/core": "^0.2.0",
30
+ "@voltx/ai": "^0.2.0",
31
+ "@voltx/server": "^0.2.0",
32
+ "@voltx/rag": "^0.2.0",
33
+ "@voltx/db": "^0.2.0"
34
+ },
35
+ "agent-app": {
36
+ "@voltx/core": "^0.2.0",
37
+ "@voltx/ai": "^0.2.0",
38
+ "@voltx/server": "^0.2.0",
39
+ "@voltx/agents": "^0.2.0",
40
+ "@voltx/memory": "^0.2.0"
41
+ }
42
+ };
43
+ const packageJson = {
44
+ name,
45
+ version: "0.1.0",
46
+ private: true,
47
+ scripts: {
48
+ dev: "tsx src/index.ts",
49
+ build: "tsc",
50
+ start: "node dist/index.js"
51
+ },
52
+ dependencies: {
53
+ ...templateDeps[template] ?? templateDeps["blank"],
54
+ ...auth === "better-auth" ? { "@voltx/auth": "^0.2.0", "better-auth": "^1.5.0" } : {},
55
+ ...auth === "jwt" ? { "@voltx/auth": "^0.2.0", "jose": "^6.0.0" } : {}
56
+ },
57
+ devDependencies: {
58
+ typescript: "^5.7.0",
59
+ tsx: "^4.21.0",
60
+ "@types/node": "^22.0.0"
61
+ }
62
+ };
63
+ fs.writeFileSync(
64
+ path.join(targetDir, "package.json"),
65
+ JSON.stringify(packageJson, null, 2)
66
+ );
67
+ const hasDb = template === "rag-app" || template === "agent-app" || auth === "better-auth";
68
+ const provider = template === "rag-app" ? "openai" : "cerebras";
69
+ const model = template === "rag-app" ? "gpt-4o" : "llama-4-scout-17b-16e";
70
+ let configContent = `import { defineConfig } from "@voltx/core";
71
+
72
+ export default defineConfig({
73
+ name: "${name}",
74
+ port: 3000,
75
+ ai: {
76
+ provider: "${provider}",
77
+ model: "${model}",
78
+ },`;
79
+ if (hasDb) {
80
+ configContent += `
81
+ db: {
82
+ url: process.env.DATABASE_URL,
83
+ },`;
84
+ }
85
+ if (auth !== "none") {
86
+ configContent += `
87
+ auth: {
88
+ provider: "${auth}",
89
+ },`;
90
+ }
91
+ configContent += `
92
+ server: {
93
+ routesDir: "src/routes",
94
+ staticDir: "public",
95
+ cors: true,
96
+ },
97
+ });
98
+ `;
99
+ fs.writeFileSync(path.join(targetDir, "voltx.config.ts"), configContent);
100
+ fs.mkdirSync(path.join(targetDir, "src", "routes", "api"), { recursive: true });
101
+ fs.mkdirSync(path.join(targetDir, "public"), { recursive: true });
102
+ fs.writeFileSync(
103
+ path.join(targetDir, "src", "index.ts"),
104
+ `import { createApp } from "@voltx/core";
105
+ import config from "../voltx.config";
106
+
107
+ const app = createApp(config);
108
+ app.start();
109
+ `
110
+ );
111
+ fs.writeFileSync(
112
+ path.join(targetDir, "src", "routes", "index.ts"),
113
+ `// GET / \u2014 Health check
114
+ import type { Context } from "@voltx/server";
115
+
116
+ export function GET(c: Context) {
117
+ return c.json({ name: "${name}", status: "ok" });
118
+ }
119
+ `
120
+ );
121
+ if (template === "chatbot" || template === "agent-app") {
122
+ fs.writeFileSync(
123
+ path.join(targetDir, "src", "routes", "api", "chat.ts"),
124
+ `// POST /api/chat \u2014 Streaming chat with conversation memory
125
+ import type { Context } from "@voltx/server";
126
+ import { streamText } from "@voltx/ai";
127
+ import { createMemory } from "@voltx/memory";
128
+
129
+ // In-memory for dev; swap to createMemory("postgres", { url }) for production
130
+ const memory = createMemory({ maxMessages: 50 });
131
+
132
+ export async function POST(c: Context) {
133
+ const { messages, conversationId = "default" } = await c.req.json();
134
+
135
+ // Store the latest user message
136
+ const lastMessage = messages[messages.length - 1];
137
+ if (lastMessage?.role === "user") {
138
+ await memory.add(conversationId, { role: "user", content: lastMessage.content });
139
+ }
140
+
141
+ // Get conversation history from memory
142
+ const history = await memory.get(conversationId);
143
+
144
+ const result = await streamText({
145
+ model: "cerebras:llama-4-scout-17b-16e",
146
+ system: "You are a helpful AI assistant.",
147
+ messages: history.map((m) => ({ role: m.role, content: m.content })),
148
+ });
149
+
150
+ // Store assistant response after stream completes
151
+ result.text.then(async (text) => {
152
+ await memory.add(conversationId, { role: "assistant", content: text });
153
+ });
154
+
155
+ return result.toSSEResponse();
156
+ }
157
+ `
158
+ );
159
+ }
160
+ if (template === "rag-app") {
161
+ fs.mkdirSync(path.join(targetDir, "src", "routes", "api", "rag"), { recursive: true });
162
+ fs.writeFileSync(
163
+ path.join(targetDir, "src", "routes", "api", "rag", "query.ts"),
164
+ `// POST /api/rag/query \u2014 Query documents with RAG
165
+ import type { Context } from "@voltx/server";
166
+ import { streamText } from "@voltx/ai";
167
+ import { createRAGPipeline, createEmbedder } from "@voltx/rag";
168
+ import { createVectorStore } from "@voltx/db";
169
+
170
+ const vectorStore = createVectorStore(); // swap to "pinecone" or "pgvector" for production
171
+ const embedder = createEmbedder({ model: "openai:text-embedding-3-small" });
172
+ const rag = createRAGPipeline({ embedder, vectorStore });
173
+
174
+ export async function POST(c: Context) {
175
+ const { question } = await c.req.json();
176
+
177
+ const context = await rag.getContext(question, { topK: 5 });
178
+
179
+ const result = await streamText({
180
+ model: "openai:gpt-4o",
181
+ system: \`Answer the user's question based on the following context. If the context doesn't contain relevant information, say so.\\n\\nContext:\\n\${context}\`,
182
+ messages: [{ role: "user", content: question }],
183
+ });
184
+
185
+ return result.toSSEResponse();
186
+ }
187
+ `
188
+ );
189
+ fs.writeFileSync(
190
+ path.join(targetDir, "src", "routes", "api", "rag", "ingest.ts"),
191
+ `// POST /api/rag/ingest \u2014 Ingest documents into the vector store
192
+ import type { Context } from "@voltx/server";
193
+ import { createRAGPipeline, createEmbedder } from "@voltx/rag";
194
+ import { createVectorStore } from "@voltx/db";
195
+
196
+ const vectorStore = createVectorStore();
197
+ const embedder = createEmbedder({ model: "openai:text-embedding-3-small" });
198
+ const rag = createRAGPipeline({ embedder, vectorStore });
199
+
200
+ export async function POST(c: Context) {
201
+ const { text, idPrefix } = await c.req.json();
202
+
203
+ if (!text || typeof text !== "string") {
204
+ return c.json({ error: "Missing 'text' field" }, 400);
205
+ }
206
+
207
+ const result = await rag.ingest(text, idPrefix ?? "doc");
208
+ return c.json({ status: "ok", chunks: result.chunks, ids: result.ids });
209
+ }
210
+ `
211
+ );
212
+ }
213
+ if (auth === "better-auth") {
214
+ fs.writeFileSync(
215
+ path.join(targetDir, "src", "routes", "api", "auth.ts"),
216
+ `// ALL /api/auth/* \u2014 Better Auth handler
217
+ import type { Context } from "@voltx/server";
218
+ import { auth } from "../../lib/auth";
219
+ import { createAuthHandler } from "@voltx/auth";
220
+
221
+ const handler = createAuthHandler(auth);
222
+
223
+ export const GET = (c: Context) => handler(c);
224
+ export const POST = (c: Context) => handler(c);
225
+ `
226
+ );
227
+ fs.mkdirSync(path.join(targetDir, "src", "lib"), { recursive: true });
228
+ fs.writeFileSync(
229
+ path.join(targetDir, "src", "lib", "auth.ts"),
230
+ `// Auth configuration \u2014 Better Auth with DB-backed sessions
231
+ import { createAuth, createAuthMiddleware } from "@voltx/auth";
232
+
233
+ export const auth = createAuth("better-auth", {
234
+ database: process.env.DATABASE_URL!,
235
+ emailAndPassword: true,
236
+ });
237
+
238
+ export const authMiddleware = createAuthMiddleware({
239
+ provider: auth,
240
+ publicPaths: ["/api/auth", "/api/health", "/"],
241
+ });
242
+ `
243
+ );
244
+ } else if (auth === "jwt") {
245
+ fs.mkdirSync(path.join(targetDir, "src", "lib"), { recursive: true });
246
+ fs.writeFileSync(
247
+ path.join(targetDir, "src", "lib", "auth.ts"),
248
+ `// Auth configuration \u2014 JWT (stateless)
249
+ import { createAuth, createAuthMiddleware } from "@voltx/auth";
250
+
251
+ export const jwt = createAuth("jwt", {
252
+ secret: process.env.JWT_SECRET!,
253
+ expiresIn: "7d",
254
+ });
255
+
256
+ export const authMiddleware = createAuthMiddleware({
257
+ provider: jwt,
258
+ publicPaths: ["/api/auth", "/api/health", "/"],
259
+ });
260
+ `
261
+ );
262
+ fs.writeFileSync(
263
+ path.join(targetDir, "src", "routes", "api", "auth.ts"),
264
+ `// POST /api/auth/login \u2014 Example JWT login route
265
+ import type { Context } from "@voltx/server";
266
+ import { jwt } from "../../lib/auth";
267
+
268
+ export async function POST(c: Context) {
269
+ const { email, password } = await c.req.json();
270
+
271
+ if (!email || !password) {
272
+ return c.json({ error: "Email and password are required" }, 400);
273
+ }
274
+
275
+ const token = await jwt.sign({ sub: email, email });
276
+ return c.json({ token });
277
+ }
278
+ `
279
+ );
280
+ }
281
+ let envContent = "";
282
+ if (template === "rag-app") {
283
+ envContent += "# \u2500\u2500\u2500 LLM Provider \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\nOPENAI_API_KEY=sk-...\n\n";
284
+ envContent += "# \u2500\u2500\u2500 Database (Neon Postgres) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nDATABASE_URL=postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/dbname?sslmode=require\n\n";
285
+ envContent += "# \u2500\u2500\u2500 Vector Database (Pinecone) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nPINECONE_API_KEY=pc-...\nPINECONE_INDEX=voltx-embeddings\n\n";
286
+ } else if (template === "chatbot" || template === "agent-app") {
287
+ envContent += "# \u2500\u2500\u2500 LLM Provider \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\nCEREBRAS_API_KEY=csk-...\n\n";
288
+ if (template === "agent-app") {
289
+ envContent += "# \u2500\u2500\u2500 Database (Neon Postgres \u2014 optional) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nDATABASE_URL=\n\n";
290
+ }
291
+ } else {
292
+ envContent += "# \u2500\u2500\u2500 LLM Provider (add your key) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# OPENAI_API_KEY=sk-...\n# CEREBRAS_API_KEY=csk-...\n\n";
293
+ }
294
+ if (auth === "better-auth") {
295
+ envContent += "# \u2500\u2500\u2500 Auth (Better Auth) \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\nBETTER_AUTH_SECRET=your-secret-key-min-32-chars-here\nBETTER_AUTH_URL=http://localhost:3000\n";
296
+ if (template !== "rag-app" && template !== "agent-app") {
297
+ envContent += "DATABASE_URL=postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/dbname?sslmode=require\n";
298
+ }
299
+ envContent += "# GITHUB_CLIENT_ID=\n# GITHUB_CLIENT_SECRET=\n\n";
300
+ } else if (auth === "jwt") {
301
+ envContent += "# \u2500\u2500\u2500 Auth (JWT) \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\u2500\nJWT_SECRET=your-jwt-secret-key\n\n";
302
+ }
303
+ envContent += "# \u2500\u2500\u2500 App \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nPORT=3000\nNODE_ENV=development\n";
304
+ fs.writeFileSync(path.join(targetDir, ".env.example"), envContent);
305
+ fs.writeFileSync(
306
+ path.join(targetDir, ".gitignore"),
307
+ "node_modules\ndist\n.env\n"
308
+ );
309
+ fs.writeFileSync(
310
+ path.join(targetDir, "tsconfig.json"),
311
+ JSON.stringify(
312
+ {
313
+ compilerOptions: {
314
+ target: "ES2022",
315
+ module: "ESNext",
316
+ moduleResolution: "bundler",
317
+ strict: true,
318
+ esModuleInterop: true,
319
+ skipLibCheck: true,
320
+ outDir: "dist",
321
+ rootDir: "src"
322
+ },
323
+ include: ["src"]
324
+ },
325
+ null,
326
+ 2
327
+ )
328
+ );
329
+ printWelcomeBanner(name);
330
+ }
331
+ var isDirectRun = typeof __require !== "undefined" && __require.main === module && process.argv[1]?.includes("create");
332
+ if (isDirectRun) {
333
+ const projectName = process.argv[2];
334
+ if (!projectName) {
335
+ console.log("Usage: create-voltx-app <project-name> [--template chatbot] [--auth jwt]");
336
+ process.exit(1);
337
+ }
338
+ const templateFlag = process.argv.indexOf("--template");
339
+ const template = templateFlag !== -1 ? process.argv[templateFlag + 1] : "blank";
340
+ const authFlag = process.argv.indexOf("--auth");
341
+ const auth = authFlag !== -1 ? process.argv[authFlag + 1] : "none";
342
+ createProject({ name: projectName, template, auth }).catch((err) => {
343
+ console.error("[voltx] Error:", err);
344
+ process.exit(1);
345
+ });
346
+ }
347
+
348
+ export {
349
+ createProject
350
+ };