lumpiajs 1.0.5 → 1.0.7

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 CHANGED
@@ -1,196 +1,151 @@
1
1
  # 🥟 LumpiaJS
2
2
 
3
3
  **Bahasa Pemrograman Web dengan Kearifan Lokal Semarangan.**
4
- _Framework ini dibuat untuk seru-seruan (have fun) dan biar bikin web jadi lebih cepat dan menyenangkan!_ (Rencananya sih gitu... wkwkwk)
4
+ Framework ini hadir sebagai solusi "Have Fun" bagi developer. Meskipun gayanya santai, LumpiaJS mengadopsi arsitektur **MVC (Model-View-Controller)** yang mirip banget sama framework sebelah (uhuk, Laravel). Jadi kamu bisa pakai struktur yang profesional!
5
5
 
6
- ## 🚀 Cara Pakai (Quick Start)
7
-
8
- Kamu bisa pilih cara yang paling enak buat mulai bikin (masak) web:
6
+ ---
9
7
 
10
- ### 1. Langsung Gas (Tanpa Install)
8
+ ## 🚀 Panduan Instalasi & Penggunaan (Lengkap)
11
9
 
12
- Kalau malas install-install, pastikan komputer kamu sudah ada Node.js, lalu langsung aja pakai `npx`:
10
+ ### Opsi A: Menggunakan Command `lumpia` (Disarankan)
13
11
 
14
- **Langkah 1: Buat Project**
12
+ **1. Install Secara Global**
15
13
 
16
14
  ```bash
17
- npx lumpiajs create-project warung-ku
15
+ npm install -g lumpiajs
18
16
  ```
19
17
 
20
- _(Atau pakai istilah lokal: `npx lumpiajs buka-cabang warung-ku`)_
21
-
22
- **Langkah 2: Masuk & Install Bumbu (Dependencies)**
23
- Penting! Kamu harus install dependencies biar `import` framework-nya jalan.
18
+ **2. Buat Project Baru**
24
19
 
25
20
  ```bash
26
- cd warung-ku
27
- npm install
21
+ lumpia create-project warung-ku
28
22
  ```
29
23
 
30
- **Langkah 3: Nyalakan Kompor (Server)**
24
+ **3. Masuk & Install Dependencies (Wajib)**
31
25
 
32
26
  ```bash
33
- npm start
27
+ cd warung-ku && npm install
34
28
  ```
35
29
 
36
- _(Atau manual: `npx lumpia dodolan`)_
37
- Websitemu bakal jalan di `http://localhost:3000`.
38
-
39
- ---
40
-
41
- ### 2. Install Global (Biar Bisa Dipakai Terus)
42
-
43
- Kalau kamu pengen perintah `lumpia` bisa dipanggil dari mana saja di terminal:
30
+ **4. Jalankan Server**
44
31
 
45
32
  ```bash
46
- # 1. Install dulu secara global
47
- npm install -g lumpiajs
33
+ lumpia kukus
34
+ ```
48
35
 
49
- # 2. Bikin project baru
50
- lumpia create-project toko-lumpia
36
+ _(Alias: `lumpia serve`)_
51
37
 
52
- # 3. Masuk folder & install npm
53
- cd toko-lumpia
54
- npm install
38
+ ---
55
39
 
56
- # 4. Jalanin server
57
- lumpia dodolan
58
- ```
40
+ ## ⚙️ Konfigurasi Environment (.env)
59
41
 
60
- **Cara Update ke Versi Terbaru:**
42
+ Setiap project LumpiaJS dilengkapi file `.env` di root folder.
61
43
 
62
- ```bash
63
- npm install -g lumpiajs@latest
44
+ ```env
45
+ BASE_URL="http://localhost:3000"
46
+ APP_ENV="local"
47
+ APP_DEBUG="true"
64
48
  ```
65
49
 
66
50
  ---
67
51
 
68
52
  ## 🏗️ Struktur Project (Standar MVC)
69
53
 
70
- LumpiaJS sekarang menggunakan arsitektur **MVC (Model-View-Controller)** yang mengikuti standar internasional, jadi developer Laravel atau Express pasti langsung paham.
71
-
72
54
  ```
73
55
  warung-ku/
74
56
  ├── app/
75
57
  │ ├── controllers/ # Otak Logika (Controller)
76
58
  │ └── models/ # Pengolah Data (Model)
77
59
  ├── routes/
78
- │ └── web.js # Rute URL
60
+ │ └── web.js # Rute URL (Jalur Akses)
79
61
  ├── views/ # Tampilan (.lmp)
62
+ ├── .env # File Konfigurasi (Environment)
80
63
  ├── package.json
81
64
  └── ...
82
65
  ```
83
66
 
84
67
  ### 1. Routes (`routes/web.js`)
85
68
 
86
- Tempat mengatur alamat URL web kamu.
69
+ Mengatur jalur URL. Sekarang sudah support parameter dinamis seperti Laravel!
87
70
 
88
71
  ```javascript
89
72
  import { Jalan } from "lumpiajs";
90
73
 
91
- // Jalan.gawe(url, 'NamaController@method')
92
- Jalan.gawe("/", "HomeController@index");
93
- Jalan.gawe("/api/products", "ProductController@index");
74
+ // Basic GET
75
+ Jalan.get("/", "HomeController@index");
76
+
77
+ // API (POST/PUT/DELETE)
78
+ Jalan.post("/api/products", "ProductController@store");
79
+ Jalan.put("/api/products/{id}", "ProductController@update");
80
+ Jalan.delete("/api/products/{id}", "ProductController@destroy");
81
+
82
+ // Dynamic Route dengan Parameter
83
+ Jalan.get("/produk/{id}", "ProductController@show");
84
+ Jalan.get("/kategori/{slug}", "CategoryController@index");
94
85
  ```
95
86
 
96
87
  ### 2. Controllers (`app/controllers`)
97
88
 
98
- Otak dari aplikasimu. Class harus meng-extend `Controller`.
89
+ Otak dari aplikasimu. Parameter dari route (misal `{id}`) otomatis masuk jadi argumen fungsi.
99
90
 
100
91
  ```javascript
101
92
  import { Controller } from "lumpiajs";
102
93
 
103
- export default class HomeController extends Controller {
104
- index() {
105
- // Tampilkan file di folder views/home.lmp
106
- // Kirim data 'pesan' ke view
107
- return this.tampil("home", {
108
- pesan: "Halo Dunia!",
109
- tanggal: new Date().toLocaleDateString(),
94
+ export default class ProductController extends Controller {
95
+ // Menangkap parameter {id} dari route
96
+ show(id) {
97
+ return this.json({
98
+ pesan: "Menampilkan produk dengan ID: " + id,
99
+ id: id,
110
100
  });
111
101
  }
102
+
103
+ index() {
104
+ return this.tampil("home", { env: this.env.APP_ENV });
105
+ }
112
106
  }
113
107
  ```
114
108
 
115
109
  ### 3. Views (`views`)
116
110
 
117
- File `.lmp` adalah tempat kamu menulis HTML, CSS, dan JS Semarangan dalam satu file.
118
- Gunakan `{{ nama_variabel }}` untuk menampilkan data dari Controller.
111
+ File berekstensi `.lmp`.
119
112
 
120
113
  ```html
121
114
  <lump>
122
- <klambi> /* CSS di sini */ h1 { color: #d35400; } </klambi>
123
-
124
- <kulit>
125
- <!-- HTML di sini -->
126
- <h1>{{ pesan }}</h1>
127
- <p>Tanggal server: {{ tanggal }}</p>
128
- </kulit>
129
-
130
- <isi>
131
- // JavaScript Client-side (Bahasa Semarangan) gawe sapa() { alert("Halo,
132
- Lur!"); }
133
- </isi>
115
+ <klambi> h1 { color: red; } </klambi>
116
+ <kulit> <h1>{{ pesan }}</h1> </kulit>
117
+ <isi> gawe sapa() { alert("Halo!"); } </isi>
134
118
  </lump>
135
119
  ```
136
120
 
137
121
  ### 4. Models (`app/models`)
138
122
 
139
- Tempat mengolah data (Database/API). Mendukung gaya penulisan ala Eloquent.
140
-
141
123
  ```javascript
142
124
  import { Model } from "lumpiajs";
143
-
144
- // Contoh penggunaan di Controller:
145
- // Model.use(dataProduk).dimana('harga', '<', 5000).kabeh();
125
+ // Model.use(data).dimana('harga', '<', 5000).kabeh();
146
126
  ```
147
127
 
148
128
  ---
149
129
 
150
130
  ## 🧐 Kamus Bahasa (Transpiler)
151
131
 
152
- Khusus di dalam tag **`<isi>`** (pada file `.lmp`), kamu bisa menggunakan sintaks unik ini:
132
+ Gunakan istilah Semarangan ini di dalam tag `<isi>` file `.lmp`:
153
133
 
154
- - `ono` `let`
155
- - `paten` `const`
156
- - `gawe` `function`
157
- - `yen` `if`
158
- - `liyane` `else`
159
- - `mandek` `return`
160
- - `ora` ➔ `!`
161
- - `panjang()` ➔ `.length`
134
+ | Bahasa Semarangan | JavaScript Asli |
135
+ | :---------------- | :-------------- |
136
+ | `ono` | `let` |
137
+ | `paten` | `const` |
138
+ | `gawe` | `function` |
139
+ | `yen` | `if` |
140
+ | `liyane` | `else` |
141
+ | `mandek` | `return` |
142
+ | `ora` | `!` |
162
143
 
163
144
  ---
164
145
 
165
- ## 🤝 Cara Lapor Masalah atau Kasih Saran
166
-
167
- Baru nemu bug? Atau punya ide jenius biar LumpiaJS makin jos? Sampaikan saja!
168
-
169
- Caranya gampang:
170
-
171
- 1. Buka link ini: [https://github.com/fastroware/lumpiajs/issues](https://github.com/fastroware/lumpiajs/issues)
172
- 2. Klik tombol warna hijau bertuliskan **"New Issue"**.
173
- 3. Isi Judul dengan jelas.
174
- 4. Jelaskan masalah atau saranmu di kolom deskripsi.
175
- 5. Klik **"Submit new issue"**.
176
-
177
- Selesai! Masukanmu akan saya baca pas lagi senggang.
146
+ ## ⚠️ DISCLAIMER
178
147
 
179
- ---
180
-
181
- ## ⚠️ DISCLAIMER (PENTING BANGET, WAJIB DIBACA!) ⚠️
182
-
183
- **LumpiaJS ini 100% project _Have Fun_ & Eksperimen.**
184
-
185
- Kami **TIDAK BERTANGGUNG JAWAB** atas segala bentuk kerugian yang mungkin terjadi akibat penggunaan software ini, termasuk tapi tidak terbatas pada:
186
-
187
- - Kebocoran data.
188
- - Hilangnya file penting.
189
- - Komputer meledak (lebay, tapi tetap saja hati-hati).
190
- - Kerugian materiil maupun immateriil lainnya.
191
-
192
- Gunakan framework ini dengan resiko ditanggung sendiri (_Use at your own risk_). Kalau ada error di production karena nekat pakai ini, jangan nyalahin kami ya! 🙏
193
-
194
- ---
148
+ **LumpiaJS ini adalah project "Have Fun" & Eksperimen Semata.**
149
+ Gunakan dengan resiko ditanggung sendiri (_Use at your own risk_).
195
150
 
196
151
  _Dibuat dengan ❤️ dan 🥟 dari Semarang._
package/bin/lumpia.js CHANGED
@@ -7,21 +7,27 @@ async function main() {
7
7
  const perintah = args[0];
8
8
  const parameter = args[1];
9
9
 
10
+ // ALIAS LIST
11
+ // create-project : buka-cabang
12
+ // serve : dodolan, kukus
13
+ // build : goreng
14
+
10
15
  if (perintah === 'create-project' || perintah === 'buka-cabang') {
11
16
  createProject(parameter);
12
17
  }
13
- else if (perintah === 'dodolan' || perintah === 'serve') {
18
+ else if (perintah === 'dodolan' || perintah === 'serve' || perintah === 'kukus') {
14
19
  serveProject();
15
20
  }
16
- else if (perintah === 'goreng') {
17
- console.log("🚧 Fitur 'goreng' saiki wis otomatis digabung karo 'dodolan' via JIT Compiler MVC.");
18
- console.log(" Silakan gunake: lumpia dodolan");
21
+ else if (perintah === 'goreng' || perintah === 'build') {
22
+ console.log("🚧 Fitur 'goreng' (build) saiki wis otomatis digabung karo 'kukus' (serve) via JIT Compiler MVC.");
23
+ console.log(" Silakan gunake: lumpia kukus (atau lumpia serve)");
19
24
  }
20
25
  else {
21
- console.log('Perintah ora dikenal.');
26
+ console.log('Perintah ora dikenal / Command not recognized.');
22
27
  console.log('------------------------------------------------');
23
- console.log('1. lumpia create-project <nama> (Bikin project)');
24
- console.log('2. lumpia dodolan (Jalanin server)');
28
+ console.log('1. lumpia create-project <nama> (Alias: buka-cabang)');
29
+ console.log('2. lumpia serve (Alias: kukus, dodolan)');
30
+ console.log('3. lumpia build (Alias: goreng)');
25
31
  console.log('------------------------------------------------');
26
32
  }
27
33
  }
package/index.js CHANGED
@@ -2,3 +2,4 @@
2
2
  export { Jalan, routes } from './lib/core/Router.js';
3
3
  export { LumpiaModel as Model } from './lib/core/Model.js';
4
4
  export { Controller } from './lib/core/Controller.js';
5
+ export { loadEnv } from './lib/core/Env.js';
@@ -14,10 +14,12 @@ const controllerTemplate = `import { Controller } from 'lumpiajs';
14
14
 
15
15
  export default class HomeController extends Controller {
16
16
  index() {
17
- // Render view in 'views' folder
17
+ // Tampilkan halaman home
18
+ // this.env bisa diakses di sini
18
19
  return this.tampil('home', {
19
20
  message: 'Welcome to LumpiaJS MVC!',
20
- author: 'Pakdhe Koding'
21
+ author: 'Pakdhe Koding',
22
+ env: this.env.APP_ENV
21
23
  });
22
24
  }
23
25
 
@@ -42,14 +44,14 @@ import ProductData from '../../app/models/Product.js';
42
44
 
43
45
  export default class ProductController extends Controller {
44
46
  index() {
45
- // Eloquent-style: Model.use(data).dimana(...).jupuk()
46
47
  const result = Model.use(ProductData)
47
48
  .dimana('price', '>', 5500)
48
49
  .jupuk();
49
50
 
50
51
  return this.json({
51
52
  status: 'success',
52
- data: result
53
+ data: result,
54
+ debug_mode: this.env.APP_DEBUG
53
55
  });
54
56
  }
55
57
  }
@@ -59,11 +61,13 @@ const viewHomeTemplate = `<lump>
59
61
  <klambi>
60
62
  h1 { color: #d35400; text-align: center; }
61
63
  .box { border: 1px solid #ddd; padding: 20px; text-align: center; margin-top: 20px; }
64
+ .badge { background: #eee; padding: 5px; border-radius: 4px; font-size: 12px; }
62
65
  </klambi>
63
66
 
64
67
  <kulit>
65
68
  <h1>{{ message }}</h1>
66
69
  <div class="box">
70
+ <span class="badge">Environment: {{ env }}</span>
67
71
  <p>Created with love by: <strong>{{ author }}</strong></p>
68
72
  <button onclick="checkPrice()">Check Price API</button>
69
73
  <br><br>
@@ -96,8 +100,8 @@ const packageJsonTemplate = (name) => `{
96
100
  "main": "routes/web.js",
97
101
  "type": "module",
98
102
  "scripts": {
99
- "start": "lumpia dodolan",
100
- "serve": "lumpia dodolan"
103
+ "start": "lumpia kukus",
104
+ "serve": "lumpia kukus"
101
105
  },
102
106
  "dependencies": {
103
107
  "lumpiajs": "latest"
@@ -105,6 +109,14 @@ const packageJsonTemplate = (name) => `{
105
109
  }
106
110
  `;
107
111
 
112
+ const envTemplate = `
113
+ BASE_URL="http://localhost:3000"
114
+ APP_ENV="local"
115
+ # Pilihan: 'local', 'development', 'production'
116
+ APP_DEBUG="true"
117
+ # Pilihan: 'true', 'false'
118
+ `;
119
+
108
120
  export function createProject(parameter) {
109
121
  const projectName = parameter;
110
122
  if (!projectName) {
@@ -120,12 +132,6 @@ export function createProject(parameter) {
120
132
 
121
133
  fs.mkdirSync(root);
122
134
 
123
- // STANDARD MVC STRUCTURE:
124
- // app/controllers
125
- // app/models
126
- // views
127
- // routes
128
-
129
135
  fs.mkdirSync(path.join(root, 'app', 'controllers'), { recursive: true });
130
136
  fs.mkdirSync(path.join(root, 'app', 'models'), { recursive: true });
131
137
  fs.mkdirSync(path.join(root, 'routes'));
@@ -133,6 +139,7 @@ export function createProject(parameter) {
133
139
 
134
140
  // Write files
135
141
  fs.writeFileSync(path.join(root, 'package.json'), packageJsonTemplate(projectName));
142
+ fs.writeFileSync(path.join(root, '.env'), envTemplate); // Create .env
136
143
  fs.writeFileSync(path.join(root, 'routes', 'web.js'), routesTemplate);
137
144
  fs.writeFileSync(path.join(root, 'app', 'controllers', 'HomeController.js'), controllerTemplate);
138
145
  fs.writeFileSync(path.join(root, 'app', 'controllers', 'ProductController.js'), productControllerTemplate);
@@ -140,10 +147,10 @@ export function createProject(parameter) {
140
147
  fs.writeFileSync(path.join(root, 'views', 'home.lmp'), viewHomeTemplate);
141
148
  fs.writeFileSync(path.join(root, 'views', 'profile.lmp'), viewProfileTemplate);
142
149
 
143
- console.log('✅ Project ready! Standard MVC Structure.');
150
+ console.log('✅ Project ready! Standard MVC Structure with .env Support.');
144
151
  console.log('----------------------------------------------------');
145
152
  console.log(`cd ${projectName}`);
146
153
  console.log('npm install');
147
- console.log('npm start');
154
+ console.log('lumpia kukus');
148
155
  console.log('----------------------------------------------------');
149
156
  }
@@ -3,21 +3,78 @@ import path from 'path';
3
3
  import http from 'http';
4
4
  import { routes } from '../core/Router.js';
5
5
  import { renderLumpia } from '../core/View.js';
6
+ import { loadEnv } from '../core/Env.js';
7
+
8
+ // Baca versi LumpiaJS global (CLI ini)
9
+ const cliPackageJson = JSON.parse(fs.readFileSync(new URL('../../package.json', import.meta.url)));
10
+
11
+ // Helper untuk mencocokkan Route dengan Parameter {id} dll
12
+ function matchRoute(definedRoute, method, pathname) {
13
+ if (definedRoute.method !== method) return null;
14
+
15
+ // 1. Exact Match
16
+ if (definedRoute.path === pathname) return { params: {} };
17
+
18
+ // 2. Dynamic Match (Regex)
19
+ // Convert /produk/{id}/{slug} -> ^\/produk\/([^\/]+)\/([^\/]+)$
20
+ const paramNames = [];
21
+ const regexPath = definedRoute.path.replace(/\{([a-zA-Z0-9_]+)\}/g, (match, name) => {
22
+ paramNames.push(name);
23
+ return '([^/]+)';
24
+ });
25
+
26
+ // Skip if no params found in definition (optimization)
27
+ if (regexPath === definedRoute.path) return null;
28
+
29
+ const regex = new RegExp(`^${regexPath}$`);
30
+ const match = pathname.match(regex);
31
+
32
+ if (match) {
33
+ const params = {};
34
+ paramNames.forEach((name, index) => {
35
+ params[name] = match[index + 1]; // capture groups start at 1
36
+ });
37
+ return { params };
38
+ }
39
+
40
+ return null;
41
+ }
6
42
 
7
43
  export async function serveProject() {
8
44
  const root = process.cwd();
9
- const routesFile = path.join(root, 'routes', 'web.js');
45
+
46
+ // --- 1. Version Check ---
47
+ const userPackageJsonPath = path.join(root, 'package.json');
48
+ if (fs.existsSync(userPackageJsonPath)) {
49
+ const userPkg = JSON.parse(fs.readFileSync(userPackageJsonPath, 'utf-8'));
50
+ const userLumpiaVer = (userPkg.dependencies && userPkg.dependencies.lumpiajs) || 'unknown';
51
+
52
+ console.log(`ℹ️ LumpiaJS CLI Version: ${cliPackageJson.version}`);
53
+ console.log(`ℹ️ Project Dependency Version: ${userLumpiaVer}`);
10
54
 
55
+ const cleanUserVer = userLumpiaVer.replace(/[^0-9.]/g, '');
56
+ if (cleanUserVer !== cliPackageJson.version && userLumpiaVer !== 'latest') {
57
+ console.log('\n⚠️ PERINGATAN BEDA VERSI!');
58
+ console.log(` Versi CLI kamu (${cliPackageJson.version}) beda dengan versi di project (${userLumpiaVer}).`);
59
+ console.log(' Saran: Update project dependencies agar sinkron.');
60
+ console.log(' Cara update: npm install lumpiajs@latest\n');
61
+ }
62
+ }
63
+
64
+ const routesFile = path.join(root, 'routes', 'web.js');
11
65
  if (!fs.existsSync(routesFile)) return console.log("❌ This is not a LumpiaJS MVC project! (Cannot find routes/web.js)");
12
66
 
13
- console.log('🔄 Loading core framework...');
14
-
67
+ // --- 2. Load ENV ---
68
+ const env = loadEnv(root);
69
+ console.log(`🌍 Environment: ${env.APP_ENV}`);
70
+ console.log(`🐛 Debug Mode: ${env.APP_DEBUG}`);
71
+
15
72
  try {
16
73
  // Load User Routes
17
74
  const userRouteUrl = path.join(root, 'routes', 'web.js');
18
75
  await import('file://' + userRouteUrl);
19
76
 
20
- console.log(`🛣️ Routes found: ${routes.length}`);
77
+ console.log(`🛣️ Routes registered: ${routes.length}`);
21
78
 
22
79
  // Start Server
23
80
  const server = http.createServer(async (req, res) => {
@@ -25,29 +82,51 @@ export async function serveProject() {
25
82
  const url = new URL(req.url, `http://${req.headers.host}`);
26
83
  const pathname = url.pathname;
27
84
 
28
- console.log(`📥 ${method} ${pathname}`);
85
+ if (env.APP_DEBUG === 'true') {
86
+ console.log(`📥 ${method} ${pathname}`);
87
+ }
88
+
89
+ // FIND MATCHING ROUTE
90
+ let match = null;
91
+ let params = {};
29
92
 
30
- const match = routes.find(r => r.path === pathname && r.method === method);
93
+ for (const route of routes) {
94
+ const result = matchRoute(route, method, pathname);
95
+ if (result) {
96
+ match = route;
97
+ params = result.params;
98
+ break;
99
+ }
100
+ }
31
101
 
32
102
  if (match) {
33
103
  try {
34
- // Action format: 'ControllerName@method'
35
104
  const [controllerName, methodName] = match.action.split('@');
36
-
37
- // Path to 'app/controllers'
38
105
  const controllerPath = path.join(root, 'app', 'controllers', controllerName + '.js');
39
106
 
40
107
  if (!fs.existsSync(controllerPath)) throw new Error(`Controller ${controllerName} not found in app/controllers!`);
41
108
 
42
- const module = await import('file://' + controllerPath + '?update=' + Date.now());
109
+ // In Development/Local, always invalidate cache
110
+ let importUrl = 'file://' + controllerPath;
111
+ if (env.APP_ENV === 'local' || env.APP_ENV === 'development') {
112
+ importUrl += '?update=' + Date.now();
113
+ }
114
+
115
+ const module = await import(importUrl);
43
116
  const ControllerClass = module.default;
44
117
  const instance = new ControllerClass();
45
118
 
119
+ // Inject ENV & Params to Controller
120
+ instance.env = env;
121
+ instance.params = params; // Available as this.params
122
+
46
123
  if (typeof instance[methodName] !== 'function') {
47
124
  throw new Error(`Method ${methodName} does not exist in ${controllerName}`);
48
125
  }
49
126
 
50
- const result = await instance[methodName]();
127
+ // Pass params as spread arguments to the method: index(id, slug)
128
+ const args = Object.values(params);
129
+ const result = await instance[methodName](...args);
51
130
 
52
131
  if (result.type === 'html') {
53
132
  res.writeHead(200, {'Content-Type': 'text/html'});
@@ -61,8 +140,12 @@ export async function serveProject() {
61
140
  }
62
141
  } catch (e) {
63
142
  console.error(e);
143
+ const errorMsg = env.APP_DEBUG === 'true'
144
+ ? `<h1>500: Server Error</h1><pre>${e.message}\n${e.stack}</pre>`
145
+ : `<h1>500: Server Error</h1><p>Something went wrong.</p>`;
146
+
64
147
  res.writeHead(500, {'Content-Type': 'text/html'});
65
- res.end(`<h1>500: Server Error</h1><pre>${e.message}\n${e.stack}</pre>`);
148
+ res.end(errorMsg);
66
149
  }
67
150
  } else {
68
151
  res.writeHead(404, {'Content-Type': 'text/html'});
@@ -72,7 +155,7 @@ export async function serveProject() {
72
155
 
73
156
  const port = 3000;
74
157
  server.listen(port, () => {
75
- console.log(`🚀 Server running at http://localhost:${port}`);
158
+ console.log(`🚀 Server running at ${env.BASE_URL || 'http://localhost:3000'}`);
76
159
  console.log(`(Press Ctrl+C to stop)`);
77
160
  });
78
161
 
@@ -0,0 +1,23 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ export function loadEnv(root) {
5
+ const envPath = path.join(root, '.env');
6
+ const env = {};
7
+
8
+ if (fs.existsSync(envPath)) {
9
+ const content = fs.readFileSync(envPath, 'utf-8');
10
+ content.split('\n').forEach(line => {
11
+ if(line.includes('=')) {
12
+ const [key, val] = line.split('=');
13
+ env[key.trim()] = val.trim().replace(/"/g, '');
14
+ }
15
+ });
16
+ } else {
17
+ // Default values if .env not found
18
+ env.BASE_URL = "http://localhost:3000";
19
+ env.APP_ENV = "local";
20
+ env.APP_DEBUG = "true";
21
+ }
22
+ return env;
23
+ }
@@ -3,12 +3,19 @@
3
3
  export const routes = [];
4
4
 
5
5
  export const Jalan = {
6
- gawe: (path, action) => routes.push({ path, action, method: 'GET' }), // GET
7
- jupuk: (path, action) => routes.push({ path, action, method: 'GET' }), // Alias GET
6
+ // Semarangan
7
+ gawe: (path, action) => routes.push({ path, action, method: 'GET' }),
8
+ jupuk: (path, action) => routes.push({ path, action, method: 'GET' }),
8
9
  kirim: (path, action) => routes.push({ path, action, method: 'POST' }),
9
10
  anyar: (path, action) => routes.push({ path, action, method: 'PUT' }),
10
11
  bucak: (path, action) => routes.push({ path, action, method: 'DELETE' }),
12
+
13
+ // Internasional (Laravel-like)
14
+ get: (path, action) => routes.push({ path, action, method: 'GET' }),
15
+ post: (path, action) => routes.push({ path, action, method: 'POST' }),
16
+ put: (path, action) => routes.push({ path, action, method: 'PUT' }),
17
+ delete: (path, action) => routes.push({ path, action, method: 'DELETE' }),
11
18
  };
12
19
 
13
- // Global Router Container (for easy access in runtime)
20
+ // Global Router Container
14
21
  global.LumpiaRouter = routes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lumpiajs",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Bahasa Pemrograman Semarangan",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -0,0 +1,6 @@
1
+
2
+ BASE_URL="http://localhost:3000"
3
+ APP_ENV="local"
4
+ # Pilihan: 'local', 'development', 'production'
5
+ APP_DEBUG="true"
6
+ # Pilihan: 'true', 'false'