wad-lab 1.0.0 → 1.0.2

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 (2) hide show
  1. package/bin/index.js +99 -51
  2. package/package.json +2 -2
package/bin/index.js CHANGED
@@ -2,66 +2,114 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
+ const readline = require('readline');
5
6
 
6
- const availableTemplates = [
7
- 'html-css-js',
8
- 'servlet-basic',
9
- 'servlet-jdbc',
10
- 'servlet-flow',
11
- 'springboot-mongo-crud',
12
- 'springboot-mongo-aggregation',
13
- 'springboot-mockmvc',
14
- 'springboot-mongo-aggregation-mockmvc',
15
- 'vue-basics',
16
- 'vue-props-emits',
17
- 'vue-router',
18
- 'vue-pinia',
19
- 'vue-router-pinia',
20
- 'vue-fetch',
21
- 'vue-axios',
22
- 'vue-router-pinia-props',
23
- 'vue-springboot-mongo-crud',
24
- 'vue-springboot-mongo-aggregation',
25
- 'vue-router-pinia-springboot'
7
+ const templates = [
8
+ { name: 'all (Unpack All 17 Templates)', value: 'all' },
9
+ { name: 'html-css-js (Form Validation & DOM)', value: 'html-css-js' },
10
+ { name: 'servlet-basic (Tomcat GET + POST)', value: 'servlet-basic' },
11
+ { name: 'servlet-jdbc (Tomcat + MySQL JDBC)', value: 'servlet-jdbc' },
12
+ { name: 'servlet-flow (HelloServlet with GET/POST)', value: 'servlet-flow' },
13
+ { name: 'springboot-mongo-crud (4-Layer REST API)', value: 'springboot-mongo-crud' },
14
+ { name: 'springboot-mongo-aggregation ($group, $sum, $avg, $sort)', value: 'springboot-mongo-aggregation' },
15
+ { name: 'springboot-mockmvc (Controller Tests)', value: 'springboot-mockmvc' },
16
+ { name: 'springboot-mongo-aggregation-mockmvc (Full Tests)', value: 'springboot-mongo-aggregation-mockmvc' },
17
+ { name: 'vue-basics (ref, reactive, computed, v-model)', value: 'vue-basics' },
18
+ { name: 'vue-props-emits (Parent/Child Component Communication)', value: 'vue-props-emits' },
19
+ { name: 'vue-router (Parent Layout & Nested Children)', value: 'vue-router' },
20
+ { name: 'vue-pinia (Centralized State Store)', value: 'vue-pinia' },
21
+ { name: 'vue-router-pinia (Router with Children + Pinia)', value: 'vue-router-pinia' },
22
+ { name: 'vue-fetch (Native fetch CRUD)', value: 'vue-fetch' },
23
+ { name: 'vue-axios (Axios CRUD Service)', value: 'vue-axios' },
24
+ { name: 'vue-router-pinia-props (Router + Pinia + Props + Emits)', value: 'vue-router-pinia-props' },
25
+ { name: 'vue-springboot-mongo-crud (Fullstack CRUD)', value: 'vue-springboot-mongo-crud' },
26
+ { name: 'vue-springboot-mongo-aggregation (Fullstack Dashboard)', value: 'vue-springboot-mongo-aggregation' },
27
+ { name: 'vue-router-pinia-springboot (Fullstack Enterprise)', value: 'vue-router-pinia-springboot' }
26
28
  ];
27
29
 
28
- const selected = process.argv[2];
29
- const targetDir = process.argv[3] || process.cwd();
30
+ let selectedIndex = 0;
31
+ const templatesRoot = path.join(__dirname, '..', 'templates');
30
32
 
31
- if (!selected || selected === 'list' || selected === '--help' || selected === '-h') {
32
- console.log('Usage: npx wad-lab <template-name> [destination-folder]');
33
- console.log('Example: npx wad-lab vue-axios my-app');
34
- console.log('Example: npx wad-lab all ./all-templates\n');
35
- console.log('Available Templates:');
36
- availableTemplates.forEach(t => console.log(' - ' + t));
37
- console.log(' - all (unpacks all templates)');
38
- process.exit(0);
39
- }
33
+ function renderMenu() {
34
+ console.clear();
35
+ console.log('=== WAD LAB STARTER TEMPLATES ===');
36
+ console.log('Use [UP / DOWN] arrow keys to navigate, press [ENTER] to select:\n');
40
37
 
41
- const templatesRoot = path.join(__dirname, '..', 'templates');
38
+ templates.forEach((t, i) => {
39
+ if (i === selectedIndex) {
40
+ console.log('> [*] ' + t.name);
41
+ } else {
42
+ console.log(' [ ] ' + t.name);
43
+ }
44
+ });
42
45
 
43
- if (selected === 'all') {
44
- const dest = path.resolve(targetDir);
45
- if (!fs.existsSync(dest)) {
46
- fs.mkdirSync(dest, { recursive: true });
47
- }
48
- fs.cpSync(templatesRoot, dest, { recursive: true });
49
- console.log('Successfully unpacked all 17 templates to: ' + dest);
50
- process.exit(0);
46
+ console.log('\nPress Ctrl+C to cancel.');
51
47
  }
52
48
 
53
- if (!availableTemplates.includes(selected)) {
54
- console.error('Error: Template "' + selected + '" not found.');
55
- console.log('Run "npx wad-lab list" to view all available templates.');
56
- process.exit(1);
57
- }
49
+ function promptFolderName(choice) {
50
+ if (process.stdin.isTTY) {
51
+ process.stdin.setRawMode(false);
52
+ }
53
+
54
+ const defaultFolder = choice === 'all' ? 'wad-all-templates' : choice;
55
+ const rl = readline.createInterface({
56
+ input: process.stdin,
57
+ output: process.stdout
58
+ });
58
59
 
59
- const src = path.join(templatesRoot, selected);
60
- const dest = path.resolve(targetDir);
60
+ console.log('\nSelected: ' + choice);
61
+ rl.question(`Enter destination folder name (default: "${defaultFolder}"): `, (answer) => {
62
+ rl.close();
63
+ const folder = answer.trim() || defaultFolder;
64
+ const dest = path.resolve(process.cwd(), folder);
61
65
 
62
- if (!fs.existsSync(dest)) {
63
- fs.mkdirSync(dest, { recursive: true });
66
+ if (!fs.existsSync(dest)) {
67
+ fs.mkdirSync(dest, { recursive: true });
68
+ }
69
+
70
+ if (choice === 'all') {
71
+ fs.cpSync(templatesRoot, dest, { recursive: true });
72
+ console.log('\nSuccessfully unpacked ALL templates into: ' + dest);
73
+ } else {
74
+ const src = path.join(templatesRoot, choice);
75
+ fs.cpSync(src, dest, { recursive: true });
76
+ console.log('\nSuccessfully unpacked [' + choice + '] into: ' + dest);
77
+ }
78
+ process.exit(0);
79
+ });
64
80
  }
65
81
 
66
- fs.cpSync(src, dest, { recursive: true });
67
- console.log('Successfully unpacked template [' + selected + '] into: ' + dest);
82
+ if (process.argv[2]) {
83
+ const arg = process.argv[2];
84
+ const found = templates.find(t => t.value === arg);
85
+ if (found) {
86
+ promptFolderName(found.value);
87
+ } else {
88
+ console.error('Unknown template: ' + arg);
89
+ process.exit(1);
90
+ }
91
+ } else {
92
+ readline.emitKeypressEvents(process.stdin);
93
+ if (process.stdin.isTTY) {
94
+ process.stdin.setRawMode(true);
95
+ }
96
+
97
+ renderMenu();
98
+
99
+ process.stdin.on('keypress', (str, key) => {
100
+ if (key.ctrl && key.name === 'c') {
101
+ process.exit(0);
102
+ }
103
+
104
+ if (key.name === 'up') {
105
+ selectedIndex = (selectedIndex - 1 + templates.length) % templates.length;
106
+ renderMenu();
107
+ } else if (key.name === 'down') {
108
+ selectedIndex = (selectedIndex + 1) % templates.length;
109
+ renderMenu();
110
+ } else if (key.name === 'return' || key.name === 'enter') {
111
+ const chosen = templates[selectedIndex].value;
112
+ promptFolderName(chosen);
113
+ }
114
+ });
115
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wad-lab",
3
- "version": "1.0.0",
4
- "description": "Lab-ready starter templates for Web Application Development",
3
+ "version": "1.0.2",
4
+ "description": "Interactive CLI for WAD Lab starter templates (Spring Boot, MongoDB, Vue 3, Servlets)",
5
5
  "bin": {
6
6
  "wad-lab": "./bin/index.js"
7
7
  },