fsdcats 1.0.0 → 1.0.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.
- package/README.md +13 -53
- package/all-practicals.txt +32 -62
- package/bin/cli.js +9 -42
- package/lib/generator.js +40 -12
- package/lib/practicalsData.js +38 -38
- package/package.json +1 -1
- package/practical-1.txt +5 -11
- package/practical-2.txt +4 -9
- package/practical-3.txt +7 -12
- package/practical-4.txt +8 -12
- package/practical-5.txt +7 -12
- package/practical-crud.txt +1 -6
package/README.md
CHANGED
|
@@ -1,63 +1,23 @@
|
|
|
1
|
-
#
|
|
1
|
+
# fsdcats
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Minimal exam code generator with automatic clipboard copy.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Usage
|
|
6
6
|
|
|
7
|
-
## 📚 Scope Covered
|
|
8
|
-
|
|
9
|
-
1. **Practical 1: Vue Directives** (`v-if`, `v-else`, `v-model`, `v-show`, `v-for`, `v-on`) ➔ `practical-1.txt`
|
|
10
|
-
2. **Practical 2: Data Binding (Props and Emits)** (Parent-to-Child & Child-to-Parent) ➔ `practical-2.txt`
|
|
11
|
-
3. **Practical 3: Document Upload & Preview (Vue 3 + Express + Multer)** ➔ `practical-3.txt`
|
|
12
|
-
4. **Practical 4: Localized State Management (Pinia Multi-Step Form)** ➔ `practical-4.txt`
|
|
13
|
-
5. **Practical 5: Routing in Nuxt and Shared Layouts** (`pages/`, `[id].vue`, `layouts/default.vue`) ➔ `practical-5.txt`
|
|
14
|
-
6. **CRUD Operations: Express + Mongoose REST API** (Create, Read, Update, Delete) ➔ `practical-crud.txt`
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## ⚡ How to Use fsdcats
|
|
19
|
-
|
|
20
|
-
Whenever you run the command for any practical, **a formatted `.txt` file is generated and automatically opened in your text editor**.
|
|
21
|
-
|
|
22
|
-
### 1. Generate via npx (Zero Installation)
|
|
23
|
-
```bash
|
|
24
|
-
npx fsdcats 1 # Generates & opens practical-1.txt
|
|
25
|
-
npx fsdcats 2 # Generates & opens practical-2.txt
|
|
26
|
-
npx fsdcats 3 # Generates & opens practical-3.txt
|
|
27
|
-
npx fsdcats 4 # Generates & opens practical-4.txt
|
|
28
|
-
npx fsdcats 5 # Generates & opens practical-5.txt
|
|
29
|
-
npx fsdcats crud # Generates & opens practical-crud.txt
|
|
30
|
-
npx fsdcats all # Generates ALL practical text files at once!
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### 2. Interactive Menu
|
|
34
|
-
Just run:
|
|
35
7
|
```bash
|
|
36
|
-
npx fsdcats
|
|
8
|
+
npx fsdcats 1 # Vue Directives
|
|
9
|
+
npx fsdcats 2 # Props & Emits
|
|
10
|
+
npx fsdcats 3 # File Upload
|
|
11
|
+
npx fsdcats 4 # Pinia Multi-Step Form
|
|
12
|
+
npx fsdcats 5 # Nuxt Routing & Layouts
|
|
13
|
+
npx fsdcats crud # Mongoose CRUD API
|
|
14
|
+
npx fsdcats all # All practicals
|
|
37
15
|
```
|
|
38
|
-
And select a number from `1` to `5`, `crud`, or `all`.
|
|
39
|
-
|
|
40
|
-
---
|
|
41
16
|
|
|
42
|
-
|
|
17
|
+
Running any command creates the `.txt` file and **automatically copies the entire text directly to your clipboard**.
|
|
43
18
|
|
|
44
|
-
|
|
45
|
-
1. **SECTION 1: STEP-BY-STEP PROJECT SETUP**
|
|
46
|
-
- Exact terminal commands (`npm create vue@latest ...`, `cd ...`, `npm install`, `npm run dev`).
|
|
47
|
-
- Every single prompt choice (e.g. selecting `No` for TypeScript, ESLint, Prettier to avoid exam errors).
|
|
48
|
-
2. **SECTION 2: COMPONENT CODE FILES**
|
|
49
|
-
- Clearly separated by visible spacing/gaps.
|
|
50
|
-
- Component Name & target file path (e.g., `COMPONENT NAME: App.vue`, `TARGET PATH: src/App.vue`).
|
|
51
|
-
- Clean, minimal code ready to copy-paste.
|
|
19
|
+
## Publish to npm
|
|
52
20
|
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## 🚀 How to Publish to npm
|
|
56
|
-
|
|
57
|
-
In your terminal (inside `/Users/spare/Downloads/fullstack`), run:
|
|
58
21
|
```bash
|
|
59
|
-
npm publish --access public --otp=
|
|
22
|
+
npm publish --access public --otp=YOUR_OTP
|
|
60
23
|
```
|
|
61
|
-
*(Replace `YOUR_6_DIGIT_OTP` with the active code from your authenticator app).*
|
|
62
|
-
|
|
63
|
-
Once published, you or your friends can run `npx fsdcats 1` on **any computer in the world**!
|
package/all-practicals.txt
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
PRACTICAL 1: VUE DIRECTIVES (V-IF/ELSE, V-SHOW, V-FOR, V-ON, V-MODEL)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
1
|
SETUP:
|
|
7
2
|
|
|
8
3
|
1. Run:
|
|
9
4
|
npm create vue@latest my-vue-p1
|
|
10
5
|
|
|
11
|
-
2.
|
|
12
|
-
Select No to all options
|
|
6
|
+
2. Prompts:
|
|
7
|
+
Select No to all options.
|
|
13
8
|
|
|
14
9
|
3. cd my-vue-p1
|
|
15
10
|
npm install
|
|
16
11
|
|
|
17
12
|
4. npm run dev
|
|
18
|
-
(App runs on http://localhost:5173)
|
|
19
13
|
|
|
20
|
-
5. Files
|
|
14
|
+
5. Files:
|
|
21
15
|
- Create src/users.json
|
|
22
|
-
- Replace src/App.vue with
|
|
16
|
+
- Replace src/App.vue with code below.
|
|
23
17
|
|
|
24
18
|
|
|
25
19
|
|
|
@@ -72,7 +66,7 @@ function handleLogout() {
|
|
|
72
66
|
|
|
73
67
|
<template>
|
|
74
68
|
<div style="font-family: sans-serif; max-width: 400px; margin: 30px auto; padding: 20px; border: 1px solid #ccc; border-radius: 8px;">
|
|
75
|
-
<!-- 1. v-if / v-else: Toggle between Login and Dashboard -->
|
|
69
|
+
<!-- 1. v-if / v-else: Toggle between Login Screen and Dashboard -->
|
|
76
70
|
<div v-if="!currentUser">
|
|
77
71
|
<h2>System Login</h2>
|
|
78
72
|
<!-- 2. v-model: Two-way input binding -->
|
|
@@ -114,17 +108,12 @@ function handleLogout() {
|
|
|
114
108
|
|
|
115
109
|
|
|
116
110
|
|
|
117
|
-
PRACTICAL 2: DATA BINDING (PROPS AND EMITS)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
111
|
SETUP:
|
|
123
112
|
|
|
124
113
|
1. Run:
|
|
125
114
|
npm create vue@latest my-vue-p2
|
|
126
115
|
|
|
127
|
-
2.
|
|
116
|
+
2. Prompts:
|
|
128
117
|
Select No to all options.
|
|
129
118
|
|
|
130
119
|
3. cd my-vue-p2
|
|
@@ -132,9 +121,9 @@ SETUP:
|
|
|
132
121
|
|
|
133
122
|
4. npm run dev
|
|
134
123
|
|
|
135
|
-
5. Files
|
|
136
|
-
- Create src/DriverCard.vue
|
|
137
|
-
- Replace src/App.vue with
|
|
124
|
+
5. Files:
|
|
125
|
+
- Create src/DriverCard.vue
|
|
126
|
+
- Replace src/App.vue with code below.
|
|
138
127
|
|
|
139
128
|
|
|
140
129
|
|
|
@@ -238,29 +227,24 @@ function addDriver() {
|
|
|
238
227
|
|
|
239
228
|
|
|
240
229
|
|
|
241
|
-
PRACTICAL 3: DOCUMENT UPLOAD & PREVIEW SYSTEM (VUE 3 + EXPRESS + MULTER)
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
230
|
SETUP:
|
|
247
231
|
|
|
248
|
-
Backend
|
|
232
|
+
Backend:
|
|
249
233
|
1. mkdir backend && cd backend
|
|
250
234
|
2. npm init -y
|
|
251
235
|
3. npm install express multer cors
|
|
252
|
-
4. Create server.js and paste
|
|
236
|
+
4. Create server.js and paste code below.
|
|
253
237
|
5. node server.js
|
|
254
238
|
(Runs on http://localhost:5000)
|
|
255
239
|
|
|
256
|
-
Frontend
|
|
257
|
-
1. In
|
|
240
|
+
Frontend:
|
|
241
|
+
1. In another terminal:
|
|
258
242
|
npm create vue@latest frontend
|
|
259
243
|
(Select No to all options)
|
|
260
244
|
2. cd frontend && npm install
|
|
261
245
|
3. npm run dev
|
|
262
246
|
(Runs on http://localhost:5173)
|
|
263
|
-
4. Replace frontend/src/App.vue with
|
|
247
|
+
4. Replace frontend/src/App.vue with code below.
|
|
264
248
|
|
|
265
249
|
|
|
266
250
|
|
|
@@ -269,7 +253,7 @@ Frontend Setup:
|
|
|
269
253
|
COMPONENTS:
|
|
270
254
|
|
|
271
255
|
|
|
272
|
-
COMPONENT: server.js
|
|
256
|
+
COMPONENT: server.js
|
|
273
257
|
PATH: backend/server.js
|
|
274
258
|
|
|
275
259
|
const express = require('express');
|
|
@@ -337,7 +321,7 @@ app.listen(5000, () => console.log('Backend running on http://localhost:5000'));
|
|
|
337
321
|
|
|
338
322
|
|
|
339
323
|
|
|
340
|
-
COMPONENT: App.vue
|
|
324
|
+
COMPONENT: App.vue
|
|
341
325
|
PATH: frontend/src/App.vue
|
|
342
326
|
|
|
343
327
|
<script setup>
|
|
@@ -418,25 +402,21 @@ onMounted(fetchDocuments)
|
|
|
418
402
|
|
|
419
403
|
|
|
420
404
|
|
|
421
|
-
PRACTICAL 4: LOCALIZED STATE MANAGEMENT (PINIA MULTI-STEP FORM)
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
405
|
SETUP:
|
|
427
406
|
|
|
428
|
-
Frontend
|
|
407
|
+
Frontend:
|
|
429
408
|
1. npm create vue@latest frontend
|
|
430
409
|
(Select YES to Pinia, No to everything else)
|
|
431
410
|
2. cd frontend && npm install
|
|
432
411
|
3. npm run dev
|
|
433
|
-
4. Create src/store.js
|
|
412
|
+
4. Create src/store.js
|
|
413
|
+
Replace src/App.vue with code below.
|
|
434
414
|
|
|
435
|
-
Backend
|
|
415
|
+
Backend:
|
|
436
416
|
1. mkdir backend && cd backend
|
|
437
417
|
2. npm init -y
|
|
438
418
|
3. npm install express mongoose cors
|
|
439
|
-
4. Create server.js and paste
|
|
419
|
+
4. Create server.js and paste code below.
|
|
440
420
|
5. node server.js
|
|
441
421
|
|
|
442
422
|
|
|
@@ -446,7 +426,7 @@ Backend Setup (MongoDB):
|
|
|
446
426
|
COMPONENTS:
|
|
447
427
|
|
|
448
428
|
|
|
449
|
-
COMPONENT: store.js
|
|
429
|
+
COMPONENT: store.js
|
|
450
430
|
PATH: frontend/src/store.js
|
|
451
431
|
|
|
452
432
|
import { defineStore } from 'pinia'
|
|
@@ -493,7 +473,7 @@ export const useApplicationStore = defineStore('application', {
|
|
|
493
473
|
|
|
494
474
|
|
|
495
475
|
|
|
496
|
-
COMPONENT: App.vue
|
|
476
|
+
COMPONENT: App.vue
|
|
497
477
|
PATH: frontend/src/App.vue
|
|
498
478
|
|
|
499
479
|
<script setup>
|
|
@@ -555,7 +535,7 @@ const store = useApplicationStore()
|
|
|
555
535
|
|
|
556
536
|
|
|
557
537
|
|
|
558
|
-
COMPONENT: server.js
|
|
538
|
+
COMPONENT: server.js
|
|
559
539
|
PATH: backend/server.js
|
|
560
540
|
|
|
561
541
|
const express = require('express');
|
|
@@ -604,11 +584,6 @@ mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/job_app_db'
|
|
|
604
584
|
|
|
605
585
|
|
|
606
586
|
|
|
607
|
-
PRACTICAL 5: ROUTING IN NUXT AND SHARED LAYOUTS
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
587
|
SETUP:
|
|
613
588
|
|
|
614
589
|
1. Run:
|
|
@@ -623,7 +598,7 @@ SETUP:
|
|
|
623
598
|
3. cd nuxt-lab && npm run dev
|
|
624
599
|
(Runs on http://localhost:3000)
|
|
625
600
|
|
|
626
|
-
4. Create
|
|
601
|
+
4. Create files inside app/ (or root):
|
|
627
602
|
- app/app.vue
|
|
628
603
|
- app/layouts/default.vue
|
|
629
604
|
- app/layouts/minimal.vue
|
|
@@ -653,7 +628,7 @@ PATH: app/app.vue
|
|
|
653
628
|
|
|
654
629
|
|
|
655
630
|
|
|
656
|
-
COMPONENT: default.vue
|
|
631
|
+
COMPONENT: default.vue
|
|
657
632
|
PATH: app/layouts/default.vue
|
|
658
633
|
|
|
659
634
|
<!-- app/layouts/default.vue: Shared Layout with persistent header & footer -->
|
|
@@ -682,7 +657,7 @@ PATH: app/layouts/default.vue
|
|
|
682
657
|
|
|
683
658
|
|
|
684
659
|
|
|
685
|
-
COMPONENT: minimal.vue
|
|
660
|
+
COMPONENT: minimal.vue
|
|
686
661
|
PATH: app/layouts/minimal.vue
|
|
687
662
|
|
|
688
663
|
<!-- app/layouts/minimal.vue: Custom headerless layout -->
|
|
@@ -699,7 +674,7 @@ PATH: app/layouts/minimal.vue
|
|
|
699
674
|
|
|
700
675
|
|
|
701
676
|
|
|
702
|
-
COMPONENT: index.vue
|
|
677
|
+
COMPONENT: index.vue
|
|
703
678
|
PATH: app/pages/index.vue
|
|
704
679
|
|
|
705
680
|
<!-- app/pages/index.vue: Root landing page (Route: /) -->
|
|
@@ -715,7 +690,7 @@ PATH: app/pages/index.vue
|
|
|
715
690
|
|
|
716
691
|
|
|
717
692
|
|
|
718
|
-
COMPONENT: about.vue
|
|
693
|
+
COMPONENT: about.vue
|
|
719
694
|
PATH: app/pages/about.vue
|
|
720
695
|
|
|
721
696
|
<!-- app/pages/about.vue: Route: /about (uses minimal layout) -->
|
|
@@ -737,7 +712,7 @@ definePageMeta({
|
|
|
737
712
|
|
|
738
713
|
|
|
739
714
|
|
|
740
|
-
COMPONENT: items/index.vue
|
|
715
|
+
COMPONENT: items/index.vue
|
|
741
716
|
PATH: app/pages/items/index.vue
|
|
742
717
|
|
|
743
718
|
<!-- app/pages/items/index.vue: Route: /items -->
|
|
@@ -767,7 +742,7 @@ const books = [
|
|
|
767
742
|
|
|
768
743
|
|
|
769
744
|
|
|
770
|
-
COMPONENT: items/[id].vue
|
|
745
|
+
COMPONENT: items/[id].vue
|
|
771
746
|
PATH: app/pages/items/[id].vue
|
|
772
747
|
|
|
773
748
|
<!-- app/pages/items/[id].vue: Dynamic Wildcard Route: /items/:id -->
|
|
@@ -813,17 +788,12 @@ const book = books.find(b => b.id === bookId)
|
|
|
813
788
|
|
|
814
789
|
|
|
815
790
|
|
|
816
|
-
PRACTICAL CRUD: EXPRESS + MONGOOSE REST API
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
791
|
SETUP:
|
|
822
792
|
|
|
823
793
|
1. mkdir crud-backend && cd crud-backend
|
|
824
794
|
2. npm init -y
|
|
825
795
|
3. npm install express mongoose
|
|
826
|
-
4. Create server.js and paste
|
|
796
|
+
4. Create server.js and paste code below.
|
|
827
797
|
5. node server.js
|
|
828
798
|
(Runs on http://localhost:5000)
|
|
829
799
|
|
package/bin/cli.js
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const path = require('path');
|
|
4
3
|
const readline = require('readline');
|
|
5
|
-
const {
|
|
6
|
-
|
|
7
|
-
function printBanner() {
|
|
8
|
-
console.log('\n============================================================');
|
|
9
|
-
console.log(' FULLSTACK PRACTICAL EXAM CHEATSHEET GENERATOR (fsdcats) ');
|
|
10
|
-
console.log('============================================================\n');
|
|
11
|
-
}
|
|
4
|
+
const { generatePracticalFile, generateAllFiles } = require('../lib/generator');
|
|
12
5
|
|
|
13
6
|
const arg = process.argv[2];
|
|
14
7
|
|
|
@@ -16,66 +9,40 @@ if (arg) {
|
|
|
16
9
|
const cleanArg = arg.toLowerCase().replace(/^p/, '');
|
|
17
10
|
|
|
18
11
|
if (cleanArg === 'all') {
|
|
19
|
-
printBanner();
|
|
20
|
-
console.log('⏳ Generating text files for ALL practicals...');
|
|
21
12
|
const results = generateAllFiles(process.cwd());
|
|
22
|
-
console.log(
|
|
23
|
-
results.forEach(r => console.log(` 📄 ${r.fileName} -> ${r.outPath}`));
|
|
24
|
-
console.log('\nText files are ready and opened for viewing!\n');
|
|
13
|
+
console.log(`Generated & copied to clipboard (${results.length} files).`);
|
|
25
14
|
process.exit(0);
|
|
26
15
|
}
|
|
27
16
|
|
|
28
17
|
const result = generatePracticalFile(cleanArg, process.cwd());
|
|
29
18
|
if (result) {
|
|
30
|
-
|
|
31
|
-
console.log(`✅ Generated: ${result.fileName}`);
|
|
32
|
-
console.log(`📍 Path: ${result.outPath}`);
|
|
33
|
-
console.log(`\nText file has been created and opened! You can copy-paste the steps and components.`);
|
|
19
|
+
console.log(`Copied to clipboard: ${result.fileName}`);
|
|
34
20
|
process.exit(0);
|
|
35
21
|
} else {
|
|
36
|
-
console.log(
|
|
22
|
+
console.log(`Unknown practical: ${arg} (use 1, 2, 3, 4, 5, crud, or all)`);
|
|
23
|
+
process.exit(1);
|
|
37
24
|
}
|
|
38
25
|
}
|
|
39
26
|
|
|
40
|
-
// Interactive menu if no argument given
|
|
41
|
-
printBanner();
|
|
42
|
-
console.log('Select a practical to generate its text file (Setup Steps + Component Code):\n');
|
|
43
|
-
|
|
44
|
-
const keys = ['1', '2', '3', '4', '5', 'crud'];
|
|
45
|
-
keys.forEach(k => {
|
|
46
|
-
console.log(` [${k}] ${practicalsData[k].title} -> (${practicalsData[k].fileName})`);
|
|
47
|
-
});
|
|
48
|
-
console.log(' [all] Generate text files for ALL practicals');
|
|
49
|
-
console.log(' [q] Quit\n');
|
|
50
|
-
|
|
51
27
|
const rl = readline.createInterface({
|
|
52
28
|
input: process.stdin,
|
|
53
29
|
output: process.stdout
|
|
54
30
|
});
|
|
55
31
|
|
|
56
|
-
rl.question('
|
|
32
|
+
rl.question('Select practical (1, 2, 3, 4, 5, crud, all): ', (answer) => {
|
|
57
33
|
rl.close();
|
|
58
34
|
const choice = answer.trim().toLowerCase().replace(/^p/, '');
|
|
59
35
|
|
|
60
|
-
if (choice === 'q') {
|
|
61
|
-
console.log('Goodbye!');
|
|
62
|
-
process.exit(0);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
36
|
if (choice === 'all') {
|
|
66
37
|
const results = generateAllFiles(process.cwd());
|
|
67
|
-
console.log(
|
|
68
|
-
results.forEach(r => console.log(` 📄 ${r.fileName}`));
|
|
69
|
-
console.log('\nText files created and opened!\n');
|
|
38
|
+
console.log(`Generated & copied to clipboard (${results.length} files).`);
|
|
70
39
|
return;
|
|
71
40
|
}
|
|
72
41
|
|
|
73
42
|
const res = generatePracticalFile(choice, process.cwd());
|
|
74
43
|
if (res) {
|
|
75
|
-
console.log(
|
|
76
|
-
console.log(`📍 Location: ${res.outPath}`);
|
|
77
|
-
console.log('\nText file created and opened!\n');
|
|
44
|
+
console.log(`Copied to clipboard: ${res.fileName}`);
|
|
78
45
|
} else {
|
|
79
|
-
console.log('
|
|
46
|
+
console.log('Invalid selection.');
|
|
80
47
|
}
|
|
81
48
|
});
|
package/lib/generator.js
CHANGED
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const { exec } = require('child_process');
|
|
3
|
+
const { exec, spawn } = require('child_process');
|
|
4
4
|
const practicalsData = require('./practicalsData');
|
|
5
5
|
|
|
6
6
|
function formatPracticalText(practical) {
|
|
7
7
|
let output = '';
|
|
8
8
|
|
|
9
|
-
// Title
|
|
10
|
-
output += `${practical.title.toUpperCase()}\n`;
|
|
11
|
-
output += `\n\n\n\n`;
|
|
12
|
-
|
|
13
|
-
// Setup Section
|
|
14
9
|
output += `SETUP:\n\n`;
|
|
15
10
|
output += `${practical.setupSteps.trim()}\n`;
|
|
16
11
|
output += `\n\n\n\n\n`;
|
|
17
12
|
|
|
18
|
-
// Components Section
|
|
19
13
|
output += `COMPONENTS:\n\n\n`;
|
|
20
14
|
|
|
21
15
|
practical.components.forEach((comp) => {
|
|
@@ -28,6 +22,27 @@ function formatPracticalText(practical) {
|
|
|
28
22
|
return output;
|
|
29
23
|
}
|
|
30
24
|
|
|
25
|
+
function copyToClipboard(text) {
|
|
26
|
+
const platform = process.platform;
|
|
27
|
+
try {
|
|
28
|
+
let proc;
|
|
29
|
+
if (platform === 'darwin') {
|
|
30
|
+
proc = spawn('pbcopy');
|
|
31
|
+
} else if (platform === 'win32') {
|
|
32
|
+
proc = spawn('clip');
|
|
33
|
+
} else {
|
|
34
|
+
proc = spawn('xclip', ['-selection', 'clipboard']);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (proc && proc.stdin) {
|
|
38
|
+
proc.stdin.write(text);
|
|
39
|
+
proc.stdin.end();
|
|
40
|
+
}
|
|
41
|
+
} catch (err) {
|
|
42
|
+
// Ignore clipboard errors if running in non-desktop/CI env
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
31
46
|
function openFile(filePath) {
|
|
32
47
|
const platform = process.platform;
|
|
33
48
|
let cmd = '';
|
|
@@ -53,6 +68,8 @@ function generatePracticalFile(idOrKey, targetDir = process.cwd()) {
|
|
|
53
68
|
const content = formatPracticalText(practical);
|
|
54
69
|
const outPath = path.join(targetDir, practical.fileName);
|
|
55
70
|
fs.writeFileSync(outPath, content, 'utf8');
|
|
71
|
+
|
|
72
|
+
copyToClipboard(content);
|
|
56
73
|
openFile(outPath);
|
|
57
74
|
|
|
58
75
|
return {
|
|
@@ -68,15 +85,25 @@ function generateAllFiles(targetDir = process.cwd()) {
|
|
|
68
85
|
let combinedText = '';
|
|
69
86
|
|
|
70
87
|
for (const key of Object.keys(practicalsData)) {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
const practical = practicalsData[key];
|
|
89
|
+
const content = formatPracticalText(practical);
|
|
90
|
+
const outPath = path.join(targetDir, practical.fileName);
|
|
91
|
+
fs.writeFileSync(outPath, content, 'utf8');
|
|
92
|
+
|
|
93
|
+
generated.push({
|
|
94
|
+
fileName: practical.fileName,
|
|
95
|
+
outPath,
|
|
96
|
+
content,
|
|
97
|
+
title: practical.title
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
combinedText += content + `\n\n\n\n\n\n`;
|
|
76
101
|
}
|
|
77
102
|
|
|
78
103
|
const combinedPath = path.join(targetDir, 'all-practicals.txt');
|
|
79
104
|
fs.writeFileSync(combinedPath, combinedText, 'utf8');
|
|
105
|
+
|
|
106
|
+
copyToClipboard(combinedText);
|
|
80
107
|
openFile(combinedPath);
|
|
81
108
|
|
|
82
109
|
generated.push({
|
|
@@ -91,6 +118,7 @@ function generateAllFiles(targetDir = process.cwd()) {
|
|
|
91
118
|
module.exports = {
|
|
92
119
|
practicalsData,
|
|
93
120
|
formatPracticalText,
|
|
121
|
+
copyToClipboard,
|
|
94
122
|
generatePracticalFile,
|
|
95
123
|
generateAllFiles,
|
|
96
124
|
openFile
|
package/lib/practicalsData.js
CHANGED
|
@@ -2,22 +2,21 @@ const practicalsData = {
|
|
|
2
2
|
'1': {
|
|
3
3
|
id: '1',
|
|
4
4
|
fileName: 'practical-1.txt',
|
|
5
|
-
title: 'Practical 1
|
|
5
|
+
title: 'Practical 1',
|
|
6
6
|
setupSteps: `1. Run:
|
|
7
7
|
npm create vue@latest my-vue-p1
|
|
8
8
|
|
|
9
|
-
2.
|
|
10
|
-
Select No to all options
|
|
9
|
+
2. Prompts:
|
|
10
|
+
Select No to all options.
|
|
11
11
|
|
|
12
12
|
3. cd my-vue-p1
|
|
13
13
|
npm install
|
|
14
14
|
|
|
15
15
|
4. npm run dev
|
|
16
|
-
(App runs on http://localhost:5173)
|
|
17
16
|
|
|
18
|
-
5. Files
|
|
17
|
+
5. Files:
|
|
19
18
|
- Create src/users.json
|
|
20
|
-
- Replace src/App.vue with
|
|
19
|
+
- Replace src/App.vue with code below.`,
|
|
21
20
|
components: [
|
|
22
21
|
{
|
|
23
22
|
name: 'users.json',
|
|
@@ -59,7 +58,7 @@ function handleLogout() {
|
|
|
59
58
|
|
|
60
59
|
<template>
|
|
61
60
|
<div style="font-family: sans-serif; max-width: 400px; margin: 30px auto; padding: 20px; border: 1px solid #ccc; border-radius: 8px;">
|
|
62
|
-
<!-- 1. v-if / v-else: Toggle between Login and Dashboard -->
|
|
61
|
+
<!-- 1. v-if / v-else: Toggle between Login Screen and Dashboard -->
|
|
63
62
|
<div v-if="!currentUser">
|
|
64
63
|
<h2>System Login</h2>
|
|
65
64
|
<!-- 2. v-model: Two-way input binding -->
|
|
@@ -97,11 +96,11 @@ function handleLogout() {
|
|
|
97
96
|
'2': {
|
|
98
97
|
id: '2',
|
|
99
98
|
fileName: 'practical-2.txt',
|
|
100
|
-
title: 'Practical 2
|
|
99
|
+
title: 'Practical 2',
|
|
101
100
|
setupSteps: `1. Run:
|
|
102
101
|
npm create vue@latest my-vue-p2
|
|
103
102
|
|
|
104
|
-
2.
|
|
103
|
+
2. Prompts:
|
|
105
104
|
Select No to all options.
|
|
106
105
|
|
|
107
106
|
3. cd my-vue-p2
|
|
@@ -109,9 +108,9 @@ function handleLogout() {
|
|
|
109
108
|
|
|
110
109
|
4. npm run dev
|
|
111
110
|
|
|
112
|
-
5. Files
|
|
113
|
-
- Create src/DriverCard.vue
|
|
114
|
-
- Replace src/App.vue with
|
|
111
|
+
5. Files:
|
|
112
|
+
- Create src/DriverCard.vue
|
|
113
|
+
- Replace src/App.vue with code below.`,
|
|
115
114
|
components: [
|
|
116
115
|
{
|
|
117
116
|
name: 'DriverCard.vue',
|
|
@@ -200,26 +199,26 @@ function addDriver() {
|
|
|
200
199
|
'3': {
|
|
201
200
|
id: '3',
|
|
202
201
|
fileName: 'practical-3.txt',
|
|
203
|
-
title: 'Practical 3
|
|
204
|
-
setupSteps: `Backend
|
|
202
|
+
title: 'Practical 3',
|
|
203
|
+
setupSteps: `Backend:
|
|
205
204
|
1. mkdir backend && cd backend
|
|
206
205
|
2. npm init -y
|
|
207
206
|
3. npm install express multer cors
|
|
208
|
-
4. Create server.js and paste
|
|
207
|
+
4. Create server.js and paste code below.
|
|
209
208
|
5. node server.js
|
|
210
209
|
(Runs on http://localhost:5000)
|
|
211
210
|
|
|
212
|
-
Frontend
|
|
213
|
-
1. In
|
|
211
|
+
Frontend:
|
|
212
|
+
1. In another terminal:
|
|
214
213
|
npm create vue@latest frontend
|
|
215
214
|
(Select No to all options)
|
|
216
215
|
2. cd frontend && npm install
|
|
217
216
|
3. npm run dev
|
|
218
217
|
(Runs on http://localhost:5173)
|
|
219
|
-
4. Replace frontend/src/App.vue with
|
|
218
|
+
4. Replace frontend/src/App.vue with code below.`,
|
|
220
219
|
components: [
|
|
221
220
|
{
|
|
222
|
-
name: 'server.js
|
|
221
|
+
name: 'server.js',
|
|
223
222
|
path: 'backend/server.js',
|
|
224
223
|
code: `const express = require('express');
|
|
225
224
|
const multer = require('multer');
|
|
@@ -283,7 +282,7 @@ app.delete('/api/documents/:id', (req, res) => {
|
|
|
283
282
|
app.listen(5000, () => console.log('Backend running on http://localhost:5000'));`
|
|
284
283
|
},
|
|
285
284
|
{
|
|
286
|
-
name: 'App.vue
|
|
285
|
+
name: 'App.vue',
|
|
287
286
|
path: 'frontend/src/App.vue',
|
|
288
287
|
code: `<script setup>
|
|
289
288
|
import { ref, onMounted } from 'vue'
|
|
@@ -359,23 +358,24 @@ onMounted(fetchDocuments)
|
|
|
359
358
|
'4': {
|
|
360
359
|
id: '4',
|
|
361
360
|
fileName: 'practical-4.txt',
|
|
362
|
-
title: 'Practical 4
|
|
363
|
-
setupSteps: `Frontend
|
|
361
|
+
title: 'Practical 4',
|
|
362
|
+
setupSteps: `Frontend:
|
|
364
363
|
1. npm create vue@latest frontend
|
|
365
364
|
(Select YES to Pinia, No to everything else)
|
|
366
365
|
2. cd frontend && npm install
|
|
367
366
|
3. npm run dev
|
|
368
|
-
4. Create src/store.js
|
|
367
|
+
4. Create src/store.js
|
|
368
|
+
Replace src/App.vue with code below.
|
|
369
369
|
|
|
370
|
-
Backend
|
|
370
|
+
Backend:
|
|
371
371
|
1. mkdir backend && cd backend
|
|
372
372
|
2. npm init -y
|
|
373
373
|
3. npm install express mongoose cors
|
|
374
|
-
4. Create server.js and paste
|
|
374
|
+
4. Create server.js and paste code below.
|
|
375
375
|
5. node server.js`,
|
|
376
376
|
components: [
|
|
377
377
|
{
|
|
378
|
-
name: 'store.js
|
|
378
|
+
name: 'store.js',
|
|
379
379
|
path: 'frontend/src/store.js',
|
|
380
380
|
code: `import { defineStore } from 'pinia'
|
|
381
381
|
|
|
@@ -418,7 +418,7 @@ export const useApplicationStore = defineStore('application', {
|
|
|
418
418
|
})`
|
|
419
419
|
},
|
|
420
420
|
{
|
|
421
|
-
name: 'App.vue
|
|
421
|
+
name: 'App.vue',
|
|
422
422
|
path: 'frontend/src/App.vue',
|
|
423
423
|
code: `<script setup>
|
|
424
424
|
import { useApplicationStore } from './store.js'
|
|
@@ -476,7 +476,7 @@ const store = useApplicationStore()
|
|
|
476
476
|
</template>`
|
|
477
477
|
},
|
|
478
478
|
{
|
|
479
|
-
name: 'server.js
|
|
479
|
+
name: 'server.js',
|
|
480
480
|
path: 'backend/server.js',
|
|
481
481
|
code: `const express = require('express');
|
|
482
482
|
const mongoose = require('mongoose');
|
|
@@ -520,7 +520,7 @@ mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/job_app_db'
|
|
|
520
520
|
'5': {
|
|
521
521
|
id: '5',
|
|
522
522
|
fileName: 'practical-5.txt',
|
|
523
|
-
title: 'Practical 5
|
|
523
|
+
title: 'Practical 5',
|
|
524
524
|
setupSteps: `1. Run:
|
|
525
525
|
npx nuxi@latest init nuxt-lab
|
|
526
526
|
|
|
@@ -533,7 +533,7 @@ mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/job_app_db'
|
|
|
533
533
|
3. cd nuxt-lab && npm run dev
|
|
534
534
|
(Runs on http://localhost:3000)
|
|
535
535
|
|
|
536
|
-
4. Create
|
|
536
|
+
4. Create files inside app/ (or root):
|
|
537
537
|
- app/app.vue
|
|
538
538
|
- app/layouts/default.vue
|
|
539
539
|
- app/layouts/minimal.vue
|
|
@@ -553,7 +553,7 @@ mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/job_app_db'
|
|
|
553
553
|
</template>`
|
|
554
554
|
},
|
|
555
555
|
{
|
|
556
|
-
name: 'default.vue
|
|
556
|
+
name: 'default.vue',
|
|
557
557
|
path: 'app/layouts/default.vue',
|
|
558
558
|
code: `<!-- app/layouts/default.vue: Shared Layout with persistent header & footer -->
|
|
559
559
|
<template>
|
|
@@ -578,7 +578,7 @@ mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/job_app_db'
|
|
|
578
578
|
</template>`
|
|
579
579
|
},
|
|
580
580
|
{
|
|
581
|
-
name: 'minimal.vue
|
|
581
|
+
name: 'minimal.vue',
|
|
582
582
|
path: 'app/layouts/minimal.vue',
|
|
583
583
|
code: `<!-- app/layouts/minimal.vue: Custom headerless layout -->
|
|
584
584
|
<template>
|
|
@@ -591,7 +591,7 @@ mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/job_app_db'
|
|
|
591
591
|
</template>`
|
|
592
592
|
},
|
|
593
593
|
{
|
|
594
|
-
name: 'index.vue
|
|
594
|
+
name: 'index.vue',
|
|
595
595
|
path: 'app/pages/index.vue',
|
|
596
596
|
code: `<!-- app/pages/index.vue: Root landing page (Route: /) -->
|
|
597
597
|
<template>
|
|
@@ -603,7 +603,7 @@ mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/job_app_db'
|
|
|
603
603
|
</template>`
|
|
604
604
|
},
|
|
605
605
|
{
|
|
606
|
-
name: 'about.vue
|
|
606
|
+
name: 'about.vue',
|
|
607
607
|
path: 'app/pages/about.vue',
|
|
608
608
|
code: `<!-- app/pages/about.vue: Route: /about (uses minimal layout) -->
|
|
609
609
|
<script setup>
|
|
@@ -621,7 +621,7 @@ definePageMeta({
|
|
|
621
621
|
</template>`
|
|
622
622
|
},
|
|
623
623
|
{
|
|
624
|
-
name: 'items/index.vue
|
|
624
|
+
name: 'items/index.vue',
|
|
625
625
|
path: 'app/pages/items/index.vue',
|
|
626
626
|
code: `<!-- app/pages/items/index.vue: Route: /items -->
|
|
627
627
|
<script setup>
|
|
@@ -647,7 +647,7 @@ const books = [
|
|
|
647
647
|
</template>`
|
|
648
648
|
},
|
|
649
649
|
{
|
|
650
|
-
name: 'items/[id].vue
|
|
650
|
+
name: 'items/[id].vue',
|
|
651
651
|
path: 'app/pages/items/[id].vue',
|
|
652
652
|
code: `<!-- app/pages/items/[id].vue: Dynamic Wildcard Route: /items/:id -->
|
|
653
653
|
<script setup>
|
|
@@ -688,11 +688,11 @@ const book = books.find(b => b.id === bookId)
|
|
|
688
688
|
'crud': {
|
|
689
689
|
id: 'crud',
|
|
690
690
|
fileName: 'practical-crud.txt',
|
|
691
|
-
title: 'Practical CRUD
|
|
691
|
+
title: 'Practical CRUD',
|
|
692
692
|
setupSteps: `1. mkdir crud-backend && cd crud-backend
|
|
693
693
|
2. npm init -y
|
|
694
694
|
3. npm install express mongoose
|
|
695
|
-
4. Create server.js and paste
|
|
695
|
+
4. Create server.js and paste code below.
|
|
696
696
|
5. node server.js
|
|
697
697
|
(Runs on http://localhost:5000)`,
|
|
698
698
|
components: [
|
package/package.json
CHANGED
package/practical-1.txt
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
PRACTICAL 1: VUE DIRECTIVES (V-IF/ELSE, V-SHOW, V-FOR, V-ON, V-MODEL)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
1
|
SETUP:
|
|
7
2
|
|
|
8
3
|
1. Run:
|
|
9
4
|
npm create vue@latest my-vue-p1
|
|
10
5
|
|
|
11
|
-
2.
|
|
12
|
-
Select No to all options
|
|
6
|
+
2. Prompts:
|
|
7
|
+
Select No to all options.
|
|
13
8
|
|
|
14
9
|
3. cd my-vue-p1
|
|
15
10
|
npm install
|
|
16
11
|
|
|
17
12
|
4. npm run dev
|
|
18
|
-
(App runs on http://localhost:5173)
|
|
19
13
|
|
|
20
|
-
5. Files
|
|
14
|
+
5. Files:
|
|
21
15
|
- Create src/users.json
|
|
22
|
-
- Replace src/App.vue with
|
|
16
|
+
- Replace src/App.vue with code below.
|
|
23
17
|
|
|
24
18
|
|
|
25
19
|
|
|
@@ -72,7 +66,7 @@ function handleLogout() {
|
|
|
72
66
|
|
|
73
67
|
<template>
|
|
74
68
|
<div style="font-family: sans-serif; max-width: 400px; margin: 30px auto; padding: 20px; border: 1px solid #ccc; border-radius: 8px;">
|
|
75
|
-
<!-- 1. v-if / v-else: Toggle between Login and Dashboard -->
|
|
69
|
+
<!-- 1. v-if / v-else: Toggle between Login Screen and Dashboard -->
|
|
76
70
|
<div v-if="!currentUser">
|
|
77
71
|
<h2>System Login</h2>
|
|
78
72
|
<!-- 2. v-model: Two-way input binding -->
|
package/practical-2.txt
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
PRACTICAL 2: DATA BINDING (PROPS AND EMITS)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
1
|
SETUP:
|
|
7
2
|
|
|
8
3
|
1. Run:
|
|
9
4
|
npm create vue@latest my-vue-p2
|
|
10
5
|
|
|
11
|
-
2.
|
|
6
|
+
2. Prompts:
|
|
12
7
|
Select No to all options.
|
|
13
8
|
|
|
14
9
|
3. cd my-vue-p2
|
|
@@ -16,9 +11,9 @@ SETUP:
|
|
|
16
11
|
|
|
17
12
|
4. npm run dev
|
|
18
13
|
|
|
19
|
-
5. Files
|
|
20
|
-
- Create src/DriverCard.vue
|
|
21
|
-
- Replace src/App.vue with
|
|
14
|
+
5. Files:
|
|
15
|
+
- Create src/DriverCard.vue
|
|
16
|
+
- Replace src/App.vue with code below.
|
|
22
17
|
|
|
23
18
|
|
|
24
19
|
|
package/practical-3.txt
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
PRACTICAL 3: DOCUMENT UPLOAD & PREVIEW SYSTEM (VUE 3 + EXPRESS + MULTER)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
1
|
SETUP:
|
|
7
2
|
|
|
8
|
-
Backend
|
|
3
|
+
Backend:
|
|
9
4
|
1. mkdir backend && cd backend
|
|
10
5
|
2. npm init -y
|
|
11
6
|
3. npm install express multer cors
|
|
12
|
-
4. Create server.js and paste
|
|
7
|
+
4. Create server.js and paste code below.
|
|
13
8
|
5. node server.js
|
|
14
9
|
(Runs on http://localhost:5000)
|
|
15
10
|
|
|
16
|
-
Frontend
|
|
17
|
-
1. In
|
|
11
|
+
Frontend:
|
|
12
|
+
1. In another terminal:
|
|
18
13
|
npm create vue@latest frontend
|
|
19
14
|
(Select No to all options)
|
|
20
15
|
2. cd frontend && npm install
|
|
21
16
|
3. npm run dev
|
|
22
17
|
(Runs on http://localhost:5173)
|
|
23
|
-
4. Replace frontend/src/App.vue with
|
|
18
|
+
4. Replace frontend/src/App.vue with code below.
|
|
24
19
|
|
|
25
20
|
|
|
26
21
|
|
|
@@ -29,7 +24,7 @@ Frontend Setup:
|
|
|
29
24
|
COMPONENTS:
|
|
30
25
|
|
|
31
26
|
|
|
32
|
-
COMPONENT: server.js
|
|
27
|
+
COMPONENT: server.js
|
|
33
28
|
PATH: backend/server.js
|
|
34
29
|
|
|
35
30
|
const express = require('express');
|
|
@@ -97,7 +92,7 @@ app.listen(5000, () => console.log('Backend running on http://localhost:5000'));
|
|
|
97
92
|
|
|
98
93
|
|
|
99
94
|
|
|
100
|
-
COMPONENT: App.vue
|
|
95
|
+
COMPONENT: App.vue
|
|
101
96
|
PATH: frontend/src/App.vue
|
|
102
97
|
|
|
103
98
|
<script setup>
|
package/practical-4.txt
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
PRACTICAL 4: LOCALIZED STATE MANAGEMENT (PINIA MULTI-STEP FORM)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
1
|
SETUP:
|
|
7
2
|
|
|
8
|
-
Frontend
|
|
3
|
+
Frontend:
|
|
9
4
|
1. npm create vue@latest frontend
|
|
10
5
|
(Select YES to Pinia, No to everything else)
|
|
11
6
|
2. cd frontend && npm install
|
|
12
7
|
3. npm run dev
|
|
13
|
-
4. Create src/store.js
|
|
8
|
+
4. Create src/store.js
|
|
9
|
+
Replace src/App.vue with code below.
|
|
14
10
|
|
|
15
|
-
Backend
|
|
11
|
+
Backend:
|
|
16
12
|
1. mkdir backend && cd backend
|
|
17
13
|
2. npm init -y
|
|
18
14
|
3. npm install express mongoose cors
|
|
19
|
-
4. Create server.js and paste
|
|
15
|
+
4. Create server.js and paste code below.
|
|
20
16
|
5. node server.js
|
|
21
17
|
|
|
22
18
|
|
|
@@ -26,7 +22,7 @@ Backend Setup (MongoDB):
|
|
|
26
22
|
COMPONENTS:
|
|
27
23
|
|
|
28
24
|
|
|
29
|
-
COMPONENT: store.js
|
|
25
|
+
COMPONENT: store.js
|
|
30
26
|
PATH: frontend/src/store.js
|
|
31
27
|
|
|
32
28
|
import { defineStore } from 'pinia'
|
|
@@ -73,7 +69,7 @@ export const useApplicationStore = defineStore('application', {
|
|
|
73
69
|
|
|
74
70
|
|
|
75
71
|
|
|
76
|
-
COMPONENT: App.vue
|
|
72
|
+
COMPONENT: App.vue
|
|
77
73
|
PATH: frontend/src/App.vue
|
|
78
74
|
|
|
79
75
|
<script setup>
|
|
@@ -135,7 +131,7 @@ const store = useApplicationStore()
|
|
|
135
131
|
|
|
136
132
|
|
|
137
133
|
|
|
138
|
-
COMPONENT: server.js
|
|
134
|
+
COMPONENT: server.js
|
|
139
135
|
PATH: backend/server.js
|
|
140
136
|
|
|
141
137
|
const express = require('express');
|
package/practical-5.txt
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
PRACTICAL 5: ROUTING IN NUXT AND SHARED LAYOUTS
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
1
|
SETUP:
|
|
7
2
|
|
|
8
3
|
1. Run:
|
|
@@ -17,7 +12,7 @@ SETUP:
|
|
|
17
12
|
3. cd nuxt-lab && npm run dev
|
|
18
13
|
(Runs on http://localhost:3000)
|
|
19
14
|
|
|
20
|
-
4. Create
|
|
15
|
+
4. Create files inside app/ (or root):
|
|
21
16
|
- app/app.vue
|
|
22
17
|
- app/layouts/default.vue
|
|
23
18
|
- app/layouts/minimal.vue
|
|
@@ -47,7 +42,7 @@ PATH: app/app.vue
|
|
|
47
42
|
|
|
48
43
|
|
|
49
44
|
|
|
50
|
-
COMPONENT: default.vue
|
|
45
|
+
COMPONENT: default.vue
|
|
51
46
|
PATH: app/layouts/default.vue
|
|
52
47
|
|
|
53
48
|
<!-- app/layouts/default.vue: Shared Layout with persistent header & footer -->
|
|
@@ -76,7 +71,7 @@ PATH: app/layouts/default.vue
|
|
|
76
71
|
|
|
77
72
|
|
|
78
73
|
|
|
79
|
-
COMPONENT: minimal.vue
|
|
74
|
+
COMPONENT: minimal.vue
|
|
80
75
|
PATH: app/layouts/minimal.vue
|
|
81
76
|
|
|
82
77
|
<!-- app/layouts/minimal.vue: Custom headerless layout -->
|
|
@@ -93,7 +88,7 @@ PATH: app/layouts/minimal.vue
|
|
|
93
88
|
|
|
94
89
|
|
|
95
90
|
|
|
96
|
-
COMPONENT: index.vue
|
|
91
|
+
COMPONENT: index.vue
|
|
97
92
|
PATH: app/pages/index.vue
|
|
98
93
|
|
|
99
94
|
<!-- app/pages/index.vue: Root landing page (Route: /) -->
|
|
@@ -109,7 +104,7 @@ PATH: app/pages/index.vue
|
|
|
109
104
|
|
|
110
105
|
|
|
111
106
|
|
|
112
|
-
COMPONENT: about.vue
|
|
107
|
+
COMPONENT: about.vue
|
|
113
108
|
PATH: app/pages/about.vue
|
|
114
109
|
|
|
115
110
|
<!-- app/pages/about.vue: Route: /about (uses minimal layout) -->
|
|
@@ -131,7 +126,7 @@ definePageMeta({
|
|
|
131
126
|
|
|
132
127
|
|
|
133
128
|
|
|
134
|
-
COMPONENT: items/index.vue
|
|
129
|
+
COMPONENT: items/index.vue
|
|
135
130
|
PATH: app/pages/items/index.vue
|
|
136
131
|
|
|
137
132
|
<!-- app/pages/items/index.vue: Route: /items -->
|
|
@@ -161,7 +156,7 @@ const books = [
|
|
|
161
156
|
|
|
162
157
|
|
|
163
158
|
|
|
164
|
-
COMPONENT: items/[id].vue
|
|
159
|
+
COMPONENT: items/[id].vue
|
|
165
160
|
PATH: app/pages/items/[id].vue
|
|
166
161
|
|
|
167
162
|
<!-- app/pages/items/[id].vue: Dynamic Wildcard Route: /items/:id -->
|
package/practical-crud.txt
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
PRACTICAL CRUD: EXPRESS + MONGOOSE REST API
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
1
|
SETUP:
|
|
7
2
|
|
|
8
3
|
1. mkdir crud-backend && cd crud-backend
|
|
9
4
|
2. npm init -y
|
|
10
5
|
3. npm install express mongoose
|
|
11
|
-
4. Create server.js and paste
|
|
6
|
+
4. Create server.js and paste code below.
|
|
12
7
|
5. node server.js
|
|
13
8
|
(Runs on http://localhost:5000)
|
|
14
9
|
|