@lotus-gui/dev 0.1.0 → 0.2.1

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 (3) hide show
  1. package/README.md +40 -4
  2. package/bin/lotus.js +226 -0
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -27,7 +27,43 @@ lotus dev main.js # Custom entry point
27
27
  - Auto-restarts on any file change
28
28
  - Kills the previous process cleanly
29
29
 
30
- ### `lotus build`
30
+ - Kills the previous process cleanly
31
+
32
+ ### `lotus init [projectName]`
33
+
34
+ Initialize a new Lotus project with interactive prompts.
35
+
36
+ ```bash
37
+ lotus init # Prompts for project name
38
+ lotus init my-app # Creates 'my-app' directory
39
+ ```
40
+
41
+ **Interactive Prompts:**
42
+ If flags are not provided, the CLI will ask for:
43
+ - Project Name (directory)
44
+ - Application Name
45
+ - Version
46
+ - Description
47
+ - Author
48
+ - Homepage / Repository URL (Important for Linux packages)
49
+ - License
50
+
51
+ **Non-Interactive Flags:**
52
+ You can skip prompts by providing flags:
53
+ ```bash
54
+ lotus init my-app --name "My App" --app-version 1.0.0 --homepage "https://example.com"
55
+ ```
56
+
57
+ | Flag | Description |
58
+ |------|-------------|
59
+ | `--name` | Application display name |
60
+ | `--app-version` | Application version (e.g., `1.0.0`) |
61
+ | `--description` | Short description |
62
+ | `--author` | Author name |
63
+ | `--homepage` | Repository or homepage URL |
64
+ | `--license` | License identifier (default: `MIT`) |
65
+
66
+ ### `lotus build`
31
67
 
32
68
  Build your application into a distributable installer package.
33
69
 
@@ -38,7 +74,7 @@ lotus build --platform linux --target rpm
38
74
 
39
75
  | Flag | Values | Default | Description |
40
76
  |------|--------|---------|-------------|
41
- | `--platform` | `linux`, `win32` | Current OS | Target platform |
77
+ | `--platform` | `linux`, `win32` | Current OS | Target platform (Windows support is experimental/WIP) |
42
78
  | `--target` | `deb`, `rpm` | `deb` | Installer format (Linux only) |
43
79
 
44
80
  **What it does:**
@@ -158,10 +194,10 @@ my-lotus-app/
158
194
  "version": "1.0.0",
159
195
  "main": "main.js",
160
196
  "dependencies": {
161
- "@lotus-gui/core": "^0.1.0"
197
+ "@lotus-gui/core": "^0.2.0"
162
198
  },
163
199
  "devDependencies": {
164
- "@lotus-gui/dev": "^0.1.0"
200
+ "@lotus-gui/dev": "^0.2.0"
165
201
  }
166
202
  }
167
203
  ```
package/bin/lotus.js CHANGED
@@ -5,6 +5,7 @@ const { spawn } = require('child_process');
5
5
  const chokidar = require('chokidar');
6
6
  const path = require('path');
7
7
  const fs = require('fs');
8
+ const prompts = require('prompts');
8
9
 
9
10
  const program = new Command();
10
11
 
@@ -253,4 +254,229 @@ exec node "/usr/lib/${options.name}/resources/app/${entryPoint}" "$@"
253
254
 
254
255
  });
255
256
 
257
+ program
258
+ .command('init [projectName]')
259
+ .description('Initialize a new Lotus project')
260
+ .option('--name <name>', 'Application name')
261
+ .option('--app-version <version>', 'Application version')
262
+ .option('--description <description>', 'Application description')
263
+ .option('--author <author>', 'Author name')
264
+ .option('--license <license>', 'License (default: MIT)')
265
+ .option('--homepage <homepage>', 'Project homepage/repository URL')
266
+ .action(async (projectName, options) => {
267
+ let targetDir = projectName;
268
+
269
+ // 1. Prompt for project directory if not provided
270
+ if (!targetDir) {
271
+ const response = await prompts({
272
+ type: 'text',
273
+ name: 'value',
274
+ message: 'Project name (directory):',
275
+ initial: 'my-lotus-app'
276
+ });
277
+ targetDir = response.value;
278
+ }
279
+
280
+ if (!targetDir) {
281
+ console.log('Operation cancelled.');
282
+ process.exit(0);
283
+ }
284
+
285
+ const projectPath = path.resolve(targetDir);
286
+ if (fs.existsSync(projectPath)) {
287
+ const { overwrite } = await prompts({
288
+ type: 'confirm',
289
+ name: 'overwrite',
290
+ message: `Directory ${targetDir} already exists. Overwrite?`,
291
+ initial: false
292
+ });
293
+ if (!overwrite) {
294
+ console.log('Aborting.');
295
+ process.exit(1);
296
+ }
297
+ }
298
+
299
+ // 2. Gather Metadata (prompts if flags missing)
300
+ const questions = [
301
+ {
302
+ type: options.name ? null : 'text',
303
+ name: 'name',
304
+ message: 'Application Name:',
305
+ initial: targetDir
306
+ },
307
+ {
308
+ type: options.appVersion ? null : 'text',
309
+ name: 'version',
310
+ message: 'Version:',
311
+ initial: '0.1.0'
312
+ },
313
+ {
314
+ type: options.description ? null : 'text',
315
+ name: 'description',
316
+ message: 'Description:',
317
+ initial: 'A Lotus desktop application'
318
+ },
319
+ {
320
+ type: options.author ? null : 'text',
321
+ name: 'author',
322
+ message: 'Author:',
323
+ initial: ''
324
+ },
325
+ {
326
+ type: options.homepage ? null : 'text',
327
+ name: 'homepage',
328
+ message: 'Homepage / Repository URL:',
329
+ initial: ''
330
+ },
331
+ {
332
+ type: options.license ? null : 'text',
333
+ name: 'license',
334
+ message: 'License:',
335
+ initial: 'MIT'
336
+ }
337
+ ];
338
+
339
+ const answers = await prompts(questions);
340
+ const metadata = { ...options, ...answers };
341
+ metadata.version = options.appVersion || answers.version;
342
+ // Clean up undefined/null
343
+ Object.keys(metadata).forEach(k => metadata[k] == null && delete metadata[k]);
344
+
345
+
346
+ // 3. Generate Files
347
+ console.log(`\nCreating project in ${projectPath}...`);
348
+ fs.mkdirSync(projectPath, { recursive: true });
349
+
350
+ // package.json
351
+ const packageJson = {
352
+ name: targetDir.toLowerCase().replace(/[^a-z0-9-]/g, '-'), // npm safe name
353
+ version: metadata.version,
354
+ description: metadata.description,
355
+ main: "main.js",
356
+ scripts: {
357
+ "start": "lotus dev main.js",
358
+ "build": "lotus build"
359
+ },
360
+ keywords: ["lotus", "desktop", "gui"],
361
+ author: metadata.author,
362
+ homepage: metadata.homepage,
363
+ license: metadata.license,
364
+ dependencies: {
365
+ "@lotus-gui/core": "latest"
366
+ },
367
+ devDependencies: {
368
+ "@lotus-gui/dev": "latest"
369
+ }
370
+ };
371
+ fs.writeFileSync(path.join(projectPath, 'package.json'), JSON.stringify(packageJson, null, 2));
372
+
373
+ // lotus.config.json
374
+ const lotusConfig = {
375
+ name: metadata.name, // Display name
376
+ version: metadata.version,
377
+ license: metadata.license,
378
+ description: metadata.description,
379
+ main: "main.js",
380
+ executableName: targetDir.toLowerCase().replace(/[^a-z0-9-]/g, '-'),
381
+ author: metadata.author,
382
+ homepage: metadata.homepage || undefined,
383
+ build: {
384
+ linux: {
385
+ wmClass: metadata.name.toLowerCase().replace(/ /g, '-'),
386
+ categories: ["Utility"]
387
+ }
388
+ }
389
+ };
390
+ // Remove undefined keys
391
+ Object.keys(lotusConfig).forEach(key => lotusConfig[key] === undefined && delete lotusConfig[key]);
392
+
393
+ fs.writeFileSync(path.join(projectPath, 'lotus.config.json'), JSON.stringify(lotusConfig, null, 4));
394
+
395
+ // main.js
396
+ const mainJs = `const { ServoWindow, app, ipcMain } = require('@lotus-gui/core');
397
+ const path = require('path');
398
+
399
+ app.warmup();
400
+
401
+ const win = new ServoWindow({
402
+ id: 'main-window',
403
+ root: path.join(__dirname, 'ui'),
404
+ index: 'index.html',
405
+ width: 1024,
406
+ height: 768,
407
+ title: "${metadata.name}",
408
+ transparent: true,
409
+ visible: false
410
+ });
411
+
412
+ win.once('frame-ready', () => win.show());
413
+
414
+ ipcMain.on('hello', (data) => {
415
+ console.log('Received from renderer:', data);
416
+ ipcMain.send('reply', { message: 'Hello from Node.js!' });
417
+ });
418
+ `;
419
+ fs.writeFileSync(path.join(projectPath, 'main.js'), mainJs);
420
+
421
+ // UI Directory
422
+ const uiDir = path.join(projectPath, 'ui');
423
+ fs.mkdirSync(uiDir);
424
+
425
+ // ui/index.html
426
+ const indexHtml = `<!DOCTYPE html>
427
+ <html>
428
+ <head>
429
+ <title>${metadata.name}</title>
430
+ <style>
431
+ body { margin: 0; padding: 0; background: transparent; font-family: sans-serif; }
432
+ .app {
433
+ background: rgba(30, 30, 30, 0.95);
434
+ color: white;
435
+ height: 100vh;
436
+ display: flex;
437
+ flex-direction: column;
438
+ align-items: center;
439
+ justify-content: center;
440
+ border-radius: 8px; /* Optional rounded corners for the view */
441
+ }
442
+ button {
443
+ padding: 10px 20px;
444
+ font-size: 16px;
445
+ cursor: pointer;
446
+ background: #646cff;
447
+ color: white;
448
+ border: none;
449
+ border-radius: 4px;
450
+ }
451
+ button:hover { background: #535bf2; }
452
+ </style>
453
+ </head>
454
+ <body>
455
+ <div class="app">
456
+ <h1>Welcome to ${metadata.name} 🪷</h1>
457
+ <p>Powered by Lotus (Servo + Node.js)</p>
458
+ <button onclick="sendMessage()">Ping Node.js</button>
459
+ <p id="response"></p>
460
+ </div>
461
+
462
+ <script>
463
+ function sendMessage() {
464
+ window.lotus.send('hello', { timestamp: Date.now() });
465
+ }
466
+
467
+ window.lotus.on('reply', (data) => {
468
+ document.getElementById('response').innerText = data.message;
469
+ });
470
+ </script>
471
+ </body>
472
+ </html>`;
473
+ fs.writeFileSync(path.join(uiDir, 'index.html'), indexHtml);
474
+
475
+ console.log(`\nāœ… Project initialized in ${projectPath}`);
476
+ console.log(`\nNext steps:`);
477
+ console.log(` cd ${targetDir}`);
478
+ console.log(` npm install`);
479
+ console.log(` npx lotus dev\n`);
480
+ });
481
+
256
482
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotus-gui/dev",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "The Lotus Toolkit",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -15,7 +15,8 @@
15
15
  "dependencies": {
16
16
  "chokidar": "^3.5.3",
17
17
  "commander": "^11.1.0",
18
- "electron-winstaller": "^5.4.0"
18
+ "electron-winstaller": "^5.4.0",
19
+ "prompts": "^2.4.2"
19
20
  },
20
21
  "optionalDependencies": {
21
22
  "electron-installer-debian": "^3.2.0",