vaderjs-native 1.0.13 → 1.0.15

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.
package/cli.ts CHANGED
@@ -5,162 +5,446 @@ import fsSync from "fs";
5
5
  import path from "path";
6
6
  import readline from "readline";
7
7
 
8
- function ask(question) {
9
- const rl = readline.createInterface({
10
- input: process.stdin,
11
- output: process.stdout,
12
- });
13
- return new Promise((resolve) =>
14
- rl.question(question + " ", (answer) => {
15
- rl.close();
16
- resolve(answer.trim());
17
- })
18
- );
8
+ const cwd = process.cwd();
9
+
10
+ /* ---------------------------------- utils --------------------------------- */
11
+
12
+ function ask(question: string): Promise<string> {
13
+ const rl = readline.createInterface({
14
+ input: process.stdin,
15
+ output: process.stdout,
16
+ });
17
+ return new Promise((resolve) =>
18
+ rl.question(question + " ", (answer) => {
19
+ rl.close();
20
+ resolve(answer.trim());
21
+ })
22
+ );
19
23
  }
20
24
 
21
- async function run(cmd: string, args: string[] = []) {
22
- try {
23
- const proc = Bun.spawn([cmd, ...args], {
24
- stdout: "inherit",
25
- stderr: "inherit",
26
- });
27
-
28
- const status = await proc.exited;
29
- if (status !== 0) {
30
- console.error(`Command failed: ${cmd} ${args.join(" ")}`);
31
- process.exit(1);
32
- }
33
- } catch (error) {
34
- console.error(`Error executing command: ${error}`);
35
- process.exit(1);
25
+ async function run(cmd: string, args: string[] = []): Promise<void> {
26
+ try {
27
+ const proc = Bun.spawn([cmd, ...args], {
28
+ stdout: "inherit",
29
+ stderr: "inherit",
30
+ });
31
+
32
+ const status = await proc.exited;
33
+ if (status !== 0) {
34
+ console.error(`Command failed: ${cmd} ${args.join(" ")}`);
35
+ process.exit(1);
36
36
  }
37
+ } catch (error) {
38
+ console.error(`Error executing command: ${error}`);
39
+ process.exit(1);
40
+ }
37
41
  }
38
42
 
39
- export async function init() {
40
- console.log("šŸš€ Welcome to Vader.js project initializer!");
43
+ function logSection(title: string) {
44
+ console.log(`\n${title}`);
45
+ console.log("─".repeat(title.length));
46
+ }
41
47
 
42
- const cwd = process.cwd();
43
- let projectDir = await ask(
44
- `Enter the directory to initialize the project (default: current dir):`
45
- );
46
- if (!projectDir) projectDir = ".";
48
+ function getFlags() {
49
+ return new Set(process.argv.slice(2));
50
+ }
47
51
 
48
- projectDir = path.resolve(cwd, projectDir);
49
- if (!fsSync.existsSync(projectDir)) {
50
- await fs.mkdir(projectDir, { recursive: true });
51
- console.log(`Created directory: ${projectDir}`);
52
- }
52
+ /* -------------------------- Vite-like Template --------------------------- */
53
53
 
54
- // Confirm Tailwind usage
55
- let useTailwind = await ask("Include TailwindCSS v4 support? (y/n):");
56
- while (!["y", "n", "yes", "no"].includes(useTailwind)) {
57
- useTailwind = await ask("Please answer 'y' or 'n':");
58
- }
59
- const wantsTailwind = useTailwind === "y" || useTailwind === "yes";
54
+ const UI_FRAMEWORKS = {
55
+ none: {
56
+ name: "None (Basic)",
57
+ deps: [],
58
+ description: "Basic setup without UI framework"
59
+ },
60
+ daisyui: {
61
+ name: "VaderUI (DaisyUI)",
62
+ deps: ["vaderjs-daisyui", "daisyui", "@tailwindcss/postcss", "autoprefixer", "postcss"],
63
+ configNeeded: true,
64
+ cssFile: `@import "tailwindcss";
65
+ @plugin "daisyui";`,
66
+ description: "A comprehensive DaisyUI component library for Vader.js"
67
+ },
68
+ bootstrap: {
69
+ name: "Bootstrap 5",
70
+ deps: ["vaderjs-bootstrap", "bootstrap"],
71
+ configNeeded: false,
72
+ cssFile: `/* Import Bootstrap CSS in your HTML */
73
+ /* Or use CDN: <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> */`,
74
+ description: "Bootstrap 5 components rebuilt for Vader.js"
75
+ }
76
+ };
60
77
 
61
- // Create folders: app, src, public
62
- const appDir = path.join(projectDir, "app");
63
- const srcDir = path.join(projectDir, "src");
64
- const publicDir = path.join(projectDir, "public");
78
+ /* ---------------------------------- init ---------------------------------- */
65
79
 
66
- for (const dir of [appDir, srcDir, publicDir]) {
67
- if (!fsSync.existsSync(dir)) {
68
- await fs.mkdir(dir, { recursive: true });
69
- console.log(`Created folder: ${dir}`);
70
- }
80
+ /* ---------------------------------- init ---------------------------------- */
81
+
82
+ export async function initProject(dir?: string) {
83
+ const flags = getFlags();
84
+ const autoYes = flags.has("--yes");
85
+
86
+ console.log("šŸš€ Initializing Vader.js project");
87
+
88
+ const projectDir = path.resolve(cwd, dir || ".");
89
+ if (!fsSync.existsSync(projectDir)) {
90
+ await fs.mkdir(projectDir, { recursive: true });
91
+ }
92
+
93
+ const files = fsSync.readdirSync(projectDir);
94
+ if (files.length && !autoYes) {
95
+ const confirm = await ask("Directory is not empty. Continue? (y/n):");
96
+ if (confirm !== "y") process.exit(0);
97
+ }
98
+
99
+ // Ask for TypeScript or JavaScript
100
+ console.log("\nSelect language:");
101
+ console.log(" 1. JavaScript (recommended for beginners)");
102
+ console.log(" 2. TypeScript (recommended for production)");
103
+
104
+ let langChoice = await ask("Choose (1-2):");
105
+ const useTypeScript = langChoice === "2";
106
+ const fileExt = useTypeScript ? "tsx" : "jsx";
107
+ const configExt = useTypeScript ? "ts" : "js";
108
+
109
+ // Ask for UI framework
110
+ console.log("\nSelect a UI framework:");
111
+ Object.entries(UI_FRAMEWORKS).forEach(([key, value], index) => {
112
+ console.log(` ${index + 1}. ${value.name}`);
113
+ console.log(` ${value.description}`);
114
+ });
115
+
116
+ let frameworkChoice = await ask(`Choose (1-${Object.keys(UI_FRAMEWORKS).length}):`);
117
+ let selectedFramework = Object.keys(UI_FRAMEWORKS)[parseInt(frameworkChoice) - 1];
118
+
119
+ while (!selectedFramework || !UI_FRAMEWORKS[selectedFramework]) {
120
+ console.log(`Invalid choice. Please select 1-${Object.keys(UI_FRAMEWORKS).length}`);
121
+ frameworkChoice = await ask(`Choose (1-${Object.keys(UI_FRAMEWORKS).length}):`);
122
+ selectedFramework = Object.keys(UI_FRAMEWORKS)[parseInt(frameworkChoice) - 1];
123
+ }
124
+
125
+ const framework = UI_FRAMEWORKS[selectedFramework];
126
+
127
+ // Ask for platform support
128
+ console.log("\nSelect platforms to support:");
129
+ const androidResponse = await ask(" Include Android support? (y/n):");
130
+ const windowsResponse = await ask(" Include Windows support? (y/n):");
131
+
132
+ const platforms = {
133
+ android: androidResponse.toLowerCase() === 'y',
134
+ windows: windowsResponse.toLowerCase() === 'y',
135
+ };
136
+
137
+ logSection("šŸ“ Creating folders");
138
+
139
+ for (const d of ["app", "public", "src"]) {
140
+ const p = path.join(projectDir, d);
141
+ if (!fsSync.existsSync(p)) {
142
+ await fs.mkdir(p, { recursive: true });
143
+ console.log(`created ${d}/`);
71
144
  }
145
+ }
146
+
147
+ // Create platform-specific asset directories
148
+ if (platforms.android) {
149
+ await fs.mkdir(path.join(projectDir, "assets/android"), { recursive: true });
150
+ }
151
+ if (platforms.windows) {
152
+ await fs.mkdir(path.join(projectDir, "assets/windows"), { recursive: true });
153
+ }
154
+
155
+ logSection("🧱 Writing files");
72
156
 
73
- // Create example app/index.jsx with counter
74
- const counterCode = wantsTailwind
75
- ? `import * as Vader from "vaderjs-native";
157
+ // Create main app component based on framework and language
158
+ let appCode = "";
159
+ if (selectedFramework === "daisyui") {
160
+ appCode = `import * as Vader from "vaderjs-native"\nimport { useState } from "vaderjs-native";
161
+ import Button from "vaderjs-daisyui/Components/Actions/Button";
162
+ import { Card } from "vaderjs-daisyui/Components/Data/Display/Card";
163
+ import { Badge } from "vaderjs-daisyui/Components/Data/Display/Badge";
76
164
 
77
- function Counter() {
78
- let [count, setCount] = Vader.useState(0);
165
+ function Main() {
166
+ const [count, setCount] = useState(0);
167
+
79
168
  return (
80
- <div class="max-w-md mx-auto p-6 bg-gray-100 rounded shadow text-center">
81
- <h1 class="text-2xl font-bold mb-4">Counter Example</h1>
82
- <p class="text-xl mb-4">Count: {count}</p>
83
- <button
84
- class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
85
- onClick={() => setCount(count + 1)}
86
- >
87
- Increment
88
- </button>
169
+ <div className="min-h-screen bg-base-200 p-8">
170
+ <div className="max-w-4xl mx-auto">
171
+ <div className="text-center mb-8">
172
+ <h1 className="text-4xl font-bold text-primary mb-4">
173
+ šŸŽ‰ Welcome to Vader.js!
174
+ </h1>
175
+ <p className="text-lg text-base-content">
176
+ With ${framework.name} components
177
+ </p>
178
+ <Badge color="primary" className="mt-2">
179
+ v1.0.0
180
+ </Badge>
181
+ </div>
182
+
183
+ <Card className="mb-6" title="Interactive Demo">
184
+ <div className="space-y-4">
185
+ <div className="flex items-center justify-between">
186
+ <div>
187
+ <p className="text-xl font-semibold">Counter: {count}</p>
188
+ <p className="text-sm text-base-content/70">
189
+ Click the button to increment
190
+ </p>
191
+ </div>
192
+ <Badge color={count > 5 ? "success" : "warning"}>
193
+ {count > 5 ? "Pro User" : "Getting Started"}
194
+ </Badge>
195
+ </div>
196
+ <div className="flex gap-3">
197
+ <Button color="primary" onClick={() => setCount(count + 1)}>
198
+ Increment
199
+ </Button>
200
+ <Button color="secondary" onClick={() => setCount(0)}>
201
+ Reset
202
+ </Button>
203
+ <Button color="accent" onClick={() => alert(\`Count is: \${count}\`)}>
204
+ Show Alert
205
+ </Button>
206
+ </div>
207
+ </div>
208
+ <div slot="actions" className="text-sm text-base-content/60">
209
+ Try editing app/index.${fileExt}
210
+ </div>
211
+ </Card>
212
+
213
+ <div className="grid md:grid-cols-2 gap-6">
214
+ <Card title="Quick Start">
215
+ <ul className="space-y-2">
216
+ <li>1. Edit <code>app/index.${fileExt}</code></li>
217
+ <li>2. Run <code>bun run dev</code></li>
218
+ <li>3. Open browser to localhost:3000</li>
219
+ </ul>
220
+ </Card>
221
+
222
+ <Card title="Features">
223
+ <ul className="space-y-2">
224
+ <li>āœ… Vader.js reactive system</li>
225
+ <li>āœ… ${framework.name} components</li>
226
+ <li>āœ… Hot reload development</li>
227
+ <li>āœ… Multi-platform support</li>
228
+ </ul>
229
+ </Card>
230
+ </div>
231
+
232
+ <div className="mt-8 text-center text-sm text-base-content/60">
233
+ Learn more at https://vaderjs.dev
234
+ </div>
235
+ </div>
89
236
  </div>
90
237
  );
91
- }
238
+ }\n Vader.render(Vader.createElement(Main), document.getElementById("app"))`;
239
+ } else if (selectedFramework === "bootstrap") {
240
+ appCode = `import * as Vader from "vaderjs-native"\nimport { useState } from "vaderjs-native";
241
+ import { Container, Alert, Button, Card, Badge } from "vaderjs-bootstrap";
242
+
243
+ function Main() {
244
+ const [count, setCount] = useState(0);
92
245
 
93
- Vader.render(Vader.createElement(Counter, null), document.getElementById("app"));
94
- `
95
- : `import * as Vader from "vaderjs-native";
246
+ return (
247
+ <Container className="py-5">
248
+ <Alert type="info" dismissible className="mb-4">
249
+ <strong>Welcome to Vader.js!</strong> This is a Bootstrap 5 starter.
250
+ </Alert>
251
+
252
+ <Card className="mb-4">
253
+ <Card.Header className="d-flex justify-content-between align-items-center">
254
+ <h5 className="mb-0">Interactive Demo</h5>
255
+ <Badge bg={count > 5 ? "success" : "warning"}>
256
+ {count > 5 ? "Advanced" : "Beginner"}
257
+ </Badge>
258
+ </Card.Header>
259
+ <Card.Body>
260
+ <p className="lead">Counter: {count}</p>
261
+ <p className="text-muted mb-3">Click the buttons to interact</p>
262
+ <div className="d-flex gap-2">
263
+ <Button variant="primary" onClick={() => setCount(count + 1)}>
264
+ Increment
265
+ </Button>
266
+ <Button variant="secondary" onClick={() => setCount(0)}>
267
+ Reset
268
+ </Button>
269
+ <Button variant="info" onClick={() => alert(\`Count is: \${count}\`)}>
270
+ Show Alert
271
+ </Button>
272
+ </div>
273
+ </Card.Body>
274
+ <Card.Footer className="text-muted">
275
+ Try editing app/index.${fileExt}
276
+ </Card.Footer>
277
+ </Card>
278
+
279
+ <div className="row">
280
+ <div className="col-md-6 mb-3">
281
+ <Card>
282
+ <Card.Body>
283
+ <Card.Title>Quick Start</Card.Title>
284
+ <ol className="mb-0">
285
+ <li>Edit <code>app/index.${fileExt}</code></li>
286
+ <li>Run <code>bun run dev</code></li>
287
+ <li>Open browser to localhost:3000</li>
288
+ </ol>
289
+ </Card.Body>
290
+ </Card>
291
+ </div>
292
+ <div className="col-md-6 mb-3">
293
+ <Card>
294
+ <Card.Body>
295
+ <Card.Title>Features</Card.Title>
296
+ <ul className="mb-0">
297
+ <li>āœ… Vader.js reactive system</li>
298
+ <li>āœ… Bootstrap 5 components</li>
299
+ <li>āœ… Hot reload development</li>
300
+ <li>āœ… Multi-platform support</li>
301
+ </ul>
302
+ </Card.Body>
303
+ </Card>
304
+ </div>
305
+ </div>
306
+
307
+ <footer className="mt-4 text-center text-muted small">
308
+ Learn more at https://vaderjs.dev
309
+ </footer>
310
+ </Container>
311
+ );
312
+ }\nVader.render(Vader.createElement(Main), document.getElementById("app"))`;
313
+ } else {
314
+ appCode = `import * as Vader from "vaderjs-native"\nimport { useState } from "vaderjs-native";
96
315
 
97
- function Counter() {
98
- let [count, setCount] = Vader.useState(0);
316
+ function Main() {
317
+ const [count, setCount] = useState(0);
318
+
99
319
  return (
100
- <div style={{ maxWidth: "300px", margin: "auto", padding: "1rem", background: "#eee", borderRadius: "8px", textAlign: "center" }}>
101
- <h1 style={{ fontWeight: "bold", marginBottom: "1rem" }}>Counter Example</h1>
102
- <p style={{ fontSize: "1.25rem", marginBottom: "1rem" }}>Count: {count}</p>
103
- <button onClick={() => setCount(count + 1)}>Increment</button>
320
+ <div style={{
321
+ maxWidth: "600px",
322
+ margin: "0 auto",
323
+ padding: "2rem",
324
+ fontFamily: "system-ui, sans-serif",
325
+ lineHeight: 1.5
326
+ }}>
327
+ <h1 style={{ textAlign: "center", color: "#333" }}>
328
+ šŸš€ Welcome to Vader.js!
329
+ </h1>
330
+
331
+ <div style={{
332
+ background: "#f8f9fa",
333
+ borderRadius: "12px",
334
+ padding: "2rem",
335
+ marginTop: "2rem",
336
+ boxShadow: "0 4px 6px rgba(0,0,0,0.1)"
337
+ }}>
338
+ <h2 style={{ marginTop: 0 }}>Interactive Demo</h2>
339
+ <p style={{ fontSize: "1.5rem", fontWeight: "bold", color: "#007bff" }}>
340
+ Counter: {count}
341
+ </p>
342
+ <p style={{ color: "#666" }}>
343
+ Click the buttons below to interact with the counter
344
+ </p>
345
+
346
+ <div style={{ display: "flex", gap: "1rem", marginTop: "1.5rem" }}>
347
+ <button
348
+ onClick={() => setCount(count + 1)}
349
+ style={{
350
+ padding: "0.75rem 1.5rem",
351
+ background: "#007bff",
352
+ color: "white",
353
+ border: "none",
354
+ borderRadius: "6px",
355
+ fontSize: "1rem",
356
+ cursor: "pointer"
357
+ }}
358
+ >
359
+ Increment
360
+ </button>
361
+
362
+ <button
363
+ onClick={() => setCount(0)}
364
+ style={{
365
+ padding: "0.75rem 1.5rem",
366
+ background: "#6c757d",
367
+ color: "white",
368
+ border: "none",
369
+ borderRadius: "6px",
370
+ fontSize: "1rem",
371
+ cursor: "pointer"
372
+ }}
373
+ >
374
+ Reset
375
+ </button>
376
+
377
+ <button
378
+ onClick={() => alert(\`Current count: \${count}\`)}
379
+ style={{
380
+ padding: "0.75rem 1.5rem",
381
+ background: "#28a745",
382
+ color: "white",
383
+ border: "none",
384
+ borderRadius: "6px",
385
+ fontSize: "1rem",
386
+ cursor: "pointer"
387
+ }}
388
+ >
389
+ Show Alert
390
+ </button>
391
+ </div>
392
+ </div>
393
+
394
+ <div style={{ marginTop: "2rem" }}>
395
+ <h3>Next Steps:</h3>
396
+ <ul>
397
+ <li>Edit <code>app/index.${fileExt}</code> to customize this page</li>
398
+ <li>Run <code>bun run dev</code> to start the development server</li>
399
+ <li>Visit <code>localhost:3000</code> in your browser</li>
400
+ <li>Check out <a href="https://vaderjs.dev">vaderjs.dev</a> for documentation</li>
401
+ </ul>
402
+ </div>
104
403
  </div>
105
404
  );
106
- }
405
+ }\nVader.render(Vader.createElement(Main), document.getElementById("app"))`;
107
406
 
108
- Vader.render(Vader.createElement(Counter, null), document.getElementById("app"));
109
- `;
407
+ }
110
408
 
111
- await fs.writeFile(path.join(appDir, "index.jsx"), counterCode);
112
- console.log(`Created example route: ${path.join("app", "index.jsx")}`);
409
+ await fs.writeFile(
410
+ path.join(projectDir, `app/index.${fileExt}`),
411
+ appCode
412
+ );
413
+ console.log(`created app/index.${fileExt}`);
113
414
 
114
- // Create public/styles.css
115
- if (wantsTailwind) {
116
- await fs.writeFile(path.join(publicDir, "styles.css"), `@import 'tailwindcss';\n`);
117
- } else {
118
- await fs.writeFile(path.join(publicDir, "styles.css"), `/* Add your styles here */\n`);
119
- }
120
- console.log(`Created public/styles.css`);
415
+ await fs.writeFile(
416
+ path.join(projectDir, "public/styles.css"),
417
+ framework.cssFile || "/* Add your global styles here */"
418
+ );
419
+ console.log(`created public/styles.css`);
121
420
 
122
- // Create minimal package.json if not exist
421
+ // Create root.css for Tailwind/DaisyUI if needed
422
+ if (selectedFramework === "daisyui") {
423
+ await fs.writeFile(
424
+ path.join(projectDir, "root.css"),
425
+ framework.cssFile
426
+ );
427
+ console.log(`created root.css (for Tailwind/DaisyUI)`);
428
+ }
123
429
 
430
+ // Create vaderjs.config.ts
431
+ let configImport = "";
432
+ let configPlugins = "[]";
124
433
 
125
- // Install dependencies: vaderjs + optionally tailwindcss, postcss plugins, autoprefixer
126
- console.log("Installing dependencies with Bun...");
127
- const deps = ["vaderjs", "autoprefixer"];
128
- if (wantsTailwind) {
129
- deps.push("tailwindcss@4", "@tailwindcss/postcss", "postcss-cli");
130
- }
131
- await run("bun", ["install", ...deps]);
132
- console.log("āœ… Dependencies installed.");
133
-
134
- // If Tailwind requested, create minimal tailwind.config.cjs and postcss.config.cjs
135
- if (wantsTailwind) {
136
- const tailwindConfig = `module.exports = {
137
- content: ["./app/**/*.{js,jsx,ts,tsx}"],
138
- theme: {
139
- extend: {},
140
- },
141
- plugins: [],
142
- };`;
143
- await fs.writeFile(path.join(projectDir, "tailwind.config.cjs"), tailwindConfig);
144
- console.log("Created tailwind.config.cjs");
145
-
146
- const postcssConfig = `export default {
147
- plugins: {
148
- "@tailwindcss/postcss": {},
149
- autoprefixer: {},
434
+ if (selectedFramework === "daisyui") {
435
+ configImport = `import daisyui from "vaderjs-daisyui";\n`;
436
+ configPlugins = "[daisyui]";
437
+ } else if (selectedFramework === "bootstrap") {
438
+ configImport = `import bootstrap from "vaderjs-bootstrap";\n`;
439
+ configPlugins = "[bootstrap]";
150
440
  }
151
- };`;
152
- await fs.writeFile(path.join(projectDir, "postcss.config.cjs"), postcssConfig);
153
- console.log("Created postcss.config.cjs");
154
- }
155
441
 
156
- // Create vaderjs.config.ts regardless, add Tailwind plugin if needed
157
- const vaderConfig = `
158
- import defineConfig from "vaderjs-native/config";
159
- import tailwind from "vaderjs-native/plugins/tailwind";
442
+ const configContent = `${configImport}import defineConfig from "vaderjs-native/config";
443
+
160
444
  export default defineConfig({
161
445
  app: {
162
- name: "ExampleVaderApp",
163
- id: "com.example.vaderapp",
446
+ name: "${path.basename(projectDir)}",
447
+ id: "com.example.${path.basename(projectDir).toLowerCase()}",
164
448
  version: {
165
449
  code: 1,
166
450
  name: "1.0.0",
@@ -168,7 +452,7 @@ export default defineConfig({
168
452
  },
169
453
 
170
454
  platforms: {
171
- android: {
455
+ ${platforms.android ? `android: {
172
456
  minSdk: 24,
173
457
  targetSdk: 34,
174
458
  permissions: [
@@ -177,88 +461,194 @@ export default defineConfig({
177
461
  ],
178
462
  icon: "./assets/android/icon.png",
179
463
  splash: "./assets/android/splash.png",
180
- },
181
-
464
+ },` : ''}
465
+
182
466
  web: {
183
- title: "VaderJS App",
467
+ title: "${path.basename(projectDir)}",
184
468
  themeColor: "#111827",
185
469
  },
186
470
 
187
- // future
188
- ios: {},
189
- windows: {},
471
+ ${platforms.windows ? `windows: {
472
+ width: 1200,
473
+ height: 800,
474
+ title: "${path.basename(projectDir)}"
475
+ },` : ''}
190
476
  },
191
477
 
192
- plugins: [tailwind]
478
+ plugins: ${configPlugins}
193
479
  });`;
194
480
 
195
- await fs.writeFile(path.join(projectDir, "vaderjs.config.ts"), vaderConfig);
196
- console.log("Created vaderjs.config.ts");
197
-
198
- // Create jsconfig.json for VSCode/IDE support
199
- const jsConfig = {
200
- compilerOptions: {
201
- jsx: "react",
202
- jsxFactory: "Vader.createElement",
203
- jsxFragmentFactory: "Fragment",
204
- },
481
+ await fs.writeFile(
482
+ path.join(projectDir, `vaderjs.config.${configExt}`),
483
+ configContent
484
+ );
485
+ console.log(`created vaderjs.config.${configExt}`);
486
+
487
+ // Create package.json if it doesn't exist
488
+ const pkgPath = path.join(projectDir, "package.json");
489
+ if (!fsSync.existsSync(pkgPath)) {
490
+ const packageJson = {
491
+ name: path.basename(projectDir),
492
+ version: "1.0.0",
493
+ type: "module",
494
+ scripts: {
495
+ dev: "bun run vaderjs dev",
496
+ build: "bun run vaderjs build",
497
+ serve: "bun run vaderjs serve"
498
+ },
499
+ dependencies: {
500
+ "vaderjs-native": "latest"
501
+ },
502
+ devDependencies: {}
205
503
  };
206
- await fs.writeFile(path.join(projectDir, "jsconfig.json"), JSON.stringify(jsConfig, null, 2));
207
- console.log("Created jsconfig.json");
208
-
209
- // Final instructions
210
- const pkgJsonPath = path.join(projectDir, "package.json");
211
-
212
- if (!fsSync.existsSync(pkgJsonPath)) {
213
- // If package.json doesn't exist, create it with basic content
214
- const pkg = {
215
- name: path.basename(projectDir),
216
- version: "1.0.0",
217
- scripts: {
218
- "android:dev": "bun run vaderjs android:dev",
219
- "android:build": "bun run vaderjs android:build",
220
- dev: "bun run vaderjs dev",
221
- build: "bun run vaderjs build",
222
- serve: "bun run vaderjs serve",
223
- },
224
- dependencies: {
225
- vaderjs: "latest",
226
- },
227
- };
228
-
229
- // If Tailwind is requested, add it to the dependencies
230
- if (wantsTailwind) {
231
- pkg.dependencies.tailwindcss = "latest";
232
- pkg.dependencies["@tailwindcss/postcss"] = "latest";
233
- pkg.dependencies.postcss = "latest";
234
- pkg.dependencies.autoprefixer = "latest";
235
- }
236
504
 
237
- await fs.writeFile(pkgJsonPath, JSON.stringify(pkg, null, 2));
238
- console.log(`Created package.json`);
239
- } else {
240
- // If package.json exists, update it by adding Tailwind if it's not there
241
- const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, "utf8"));
242
-
243
- // Only update the dependencies and scripts if Tailwind is enabled
244
- if (wantsTailwind && !pkgJson.dependencies.tailwindcss) {
245
- pkgJson.dependencies.tailwindcss = "latest";
246
- pkgJson.dependencies["@tailwindcss/postcss"] = "latest";
247
- pkgJson.dependencies.postcss = "latest";
248
- pkgJson.dependencies.autoprefixer = "latest";
249
- }
505
+ // Add TypeScript if selected
506
+ if (useTypeScript) {
507
+ packageJson.devDependencies = {
508
+ ...packageJson.devDependencies,
509
+ "typescript": "^5.0.0",
510
+ "@types/bun": "latest",
511
+ "vaderjs-types"
512
+ };
513
+ }
250
514
 
251
- // Ensure the scripts are in place (if they're not there already)
252
- if (!pkgJson.scripts) pkgJson.scripts = {};
253
- pkgJson.scripts.start = pkgJson.scripts.start || "bun run vaderjs build && bun run vaderjs serve";
254
- pkgJson.scripts.build = pkgJson.scripts.build || "bun run vaderjs build";
255
- pkgJson.scripts.dev = pkgJson.scripts.dev || "bun run vaderjs dev";
515
+ // Add UI framework dependencies
516
+ if (selectedFramework !== "none") {
517
+ for (const dep of framework.deps) {
518
+ if (dep.startsWith("vaderjs-")) {
519
+ packageJson.dependencies[dep] = "latest";
520
+ } else {
521
+ packageJson.devDependencies[dep] = "latest";
522
+ }
523
+ }
524
+ }
256
525
 
257
- await fs.writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
258
- console.log(`Updated package.json`);
526
+ // Add platform-specific scripts
527
+ if (platforms.android) {
528
+ packageJson.scripts["android:dev"] = "bun run vaderjs android:dev";
529
+ packageJson.scripts["android:build"] = "bun run vaderjs android:build";
530
+ }
531
+ if (platforms.windows) {
532
+ packageJson.scripts["windows:dev"] = "bun run vaderjs windows:dev";
533
+ packageJson.scripts["windows:build"] = "bun run vaderjs windows:build";
259
534
  }
260
535
 
261
- console.log(`\nšŸŽ‰ Vader.js project initialized at:\n${projectDir}`);
262
- console.log(`Run cd ${projectDir} to navigate into the project folder`);
263
- console.log("Run `bun run dev` or your build script to get started.");
536
+ await fs.writeFile(pkgPath, JSON.stringify(packageJson, null, 2));
537
+ console.log(`created package.json`);
538
+ }
539
+
540
+ logSection("šŸ“¦ Installing dependencies");
541
+ await run("bun", ["install", "--force"]);
542
+
543
+ console.log("\nāœ… Project ready!");
544
+ console.log(`\nNext steps:`);
545
+ console.log(` cd ${path.relative(cwd, projectDir)}`);
546
+ console.log(` bun run dev`);
547
+ console.log(` Open http://localhost:3000`);
548
+
549
+ if (selectedFramework === "daisyui") {
550
+ console.log(`\nVaderUI components available:`);
551
+ console.log(` import Button from 'vaderjs-daisyui/Components/Actions/Button'`);
552
+ console.log(` import { Card } from 'vaderjs-daisyui/Components/Data/Display/Card'`);
553
+ }
554
+
555
+ if (selectedFramework === "bootstrap") {
556
+ console.log(`\nBootstrap components available:`);
557
+ console.log(` import { Button, Card } from 'vaderjs-bootstrap'`);
558
+ }
264
559
  }
560
+
561
+ /* ---------------------------------- add ----------------------------------- */
562
+
563
+ export async function addPlugin(name: string) {
564
+ if (!name) {
565
+ console.error("Please specify a plugin to add.");
566
+ process.exit(1);
567
+ }
568
+
569
+ const flags = getFlags();
570
+ const force = flags.has("--force");
571
+
572
+ const pkgName = name.startsWith("vaderjs-") ? name : `vaderjs-${name}`;
573
+ const importName = pkgName.replace(/^vaderjs-/, "").replace(/-/g, "_");
574
+
575
+ logSection(`āž• Adding plugin: ${pkgName}`);
576
+
577
+ const args = ["add", pkgName];
578
+ if (force) args.push("--force");
579
+
580
+ await run("bun", args);
581
+
582
+ const configPath = path.join(cwd, "vaderjs.config.ts");
583
+ if (!fsSync.existsSync(configPath)) {
584
+ console.warn("āš ļø vaderjs.config.ts not found, skipping registration");
585
+ return;
586
+ }
587
+
588
+ let config = await fs.readFile(configPath, "utf8");
589
+
590
+ if (config.includes(`from "${pkgName}"`)) {
591
+ console.log("ā„¹ļø Plugin already registered");
592
+ return;
593
+ }
594
+
595
+ config =
596
+ `import ${importName} from "${pkgName}";\n` +
597
+ config.replace(/plugins:\s*\[/, `plugins: [${importName}, `);
598
+
599
+ await fs.writeFile(configPath, config);
600
+ console.log("āœ” Plugin registered");
601
+ }
602
+
603
+ /* -------------------------------- remove ---------------------------------- */
604
+
605
+ export async function removePlugin(name: string) {
606
+ if (!name) {
607
+ console.error("Please specify a plugin to remove.");
608
+ process.exit(1);
609
+ }
610
+
611
+ const pkgName = name.startsWith("vaderjs-") ? name : `vaderjs-${name}`;
612
+ const importName = pkgName.replace(/^vaderjs-/, "").replace(/-/g, "_");
613
+
614
+ logSection(`āž– Removing plugin: ${pkgName}`);
615
+
616
+ await run("bun", ["remove", pkgName]);
617
+
618
+ const configPath = path.join(cwd, "vaderjs.config.ts");
619
+ if (!fsSync.existsSync(configPath)) return;
620
+
621
+ let config = await fs.readFile(configPath, "utf8");
622
+
623
+ config = config
624
+ .replace(new RegExp(`import ${importName} from ".*?";\\n?`, "g"), "")
625
+ .replace(new RegExp(`\\b${importName},?\\s*`, "g"), "");
626
+
627
+ await fs.writeFile(configPath, config);
628
+ console.log("āœ” Plugin removed");
629
+ }
630
+
631
+ /* ---------------------------------- list ---------------------------------- */
632
+
633
+ export async function listPlugins() {
634
+ const pkgPath = path.join(cwd, "package.json");
635
+ if (!fsSync.existsSync(pkgPath)) {
636
+ console.log("No package.json found.");
637
+ return;
638
+ }
639
+
640
+ const pkg = JSON.parse(await fs.readFile(pkgPath, "utf8"));
641
+ const deps = Object.keys(pkg.dependencies || {}).filter((d) =>
642
+ d.startsWith("vaderjs-")
643
+ );
644
+
645
+ if (!deps.length) {
646
+ console.log("No Vader plugins installed.");
647
+ return;
648
+ }
649
+
650
+ logSection("šŸ”Œ Installed Vader plugins");
651
+ deps.forEach((d) => console.log("•", d));
652
+ }
653
+
654
+