kaelum 1.3.4 → 1.3.6

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,258 +1,258 @@
1
- <div align="center">
2
-
3
- <h1>Kaelum</h1>
4
-
5
- [![npm version](https://img.shields.io/npm/v/kaelum)](https://www.npmjs.com/package/kaelum)
6
- [![Build Status](https://github.com/MatheusCampagnolo/kaelum/actions/workflows/deploy-docs.yml/badge.svg)](https://github.com/MatheusCampagnolo/kaelum/actions)
7
- [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
8
- [![Docs](https://img.shields.io/badge/docs-online-blue)](https://matheuscampagnolo.github.io/kaelum/)
9
-
10
- **Kaelum.js** — Minimalist Node.js framework to simplify creation of web pages and REST APIs.
11
- Designed for students and developers who want a fast, opinionated project scaffold and a small, friendly API that encapsulates common Express.js boilerplate.
12
-
13
- 👉 [**Read the full documentation here**](https://matheuscampagnolo.github.io/kaelum/)
14
-
15
- **If Kaelum helps you, consider supporting its development:**
16
-
17
- <a href='https://ko-fi.com/Z8Z51NK4KT' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
18
-
19
- </div>
20
-
21
- ## 🚀 Quick start
22
-
23
- Create a new project (interactive):
24
-
25
- ```bash
26
- npx kaelum create
27
- ```
28
-
29
- Or create non-interactively (project name + template):
30
-
31
- ```bash
32
- npx kaelum create my-app --template web
33
- # or
34
- npx kaelum create my-api --template api
35
- ```
36
-
37
- Then:
38
-
39
- ```bash
40
- cd my-app
41
- npm install
42
- npm start
43
- ```
44
-
45
- > No need to install Kaelum globally — `npx` handles execution.
46
-
47
- ---
48
-
49
- ## 📦 What Kaelum provides
50
-
51
- - CLI that scaffolds a ready-to-run project (Web or API template) using an opinionated **MVC** structure.
52
- - Thin abstraction layer over **Express.js** that:
53
-
54
- - automates JSON / URL-encoded parsing by default,
55
- - automatically configures common security middlewares via `setConfig` (CORS, Helmet),
56
- - exposes a small, easy-to-learn API for routes, middleware and configuration.
57
-
58
- - Small set of helpers for common tasks: `start`, `addRoute`, `apiRoute`, `setConfig`, `static`, `redirect`, `healthCheck`, `useErrorHandler`, and more.
59
-
60
- Kaelum aims to reduce the initial setup burden while keeping flexibility for advanced users.
61
-
62
- ---
63
-
64
- ## 📁 Template structures
65
-
66
- ### Web template (`--template web`)
67
-
68
- ```
69
- my-web-app/
70
- ├── public/ # Static files (CSS, JS)
71
- │ └── style.css
72
- ├── views/ # HTML templates
73
- │ └── index.html
74
- ├── controllers/ # Controller logic (MVC)
75
- │ └── .gitkeep
76
- ├── middlewares/ # Custom middlewares
77
- │ └── logger.js
78
- ├── routes.js # Route definitions (example uses Kaelum helpers)
79
- ├── app.js # Server initialization (uses Kaelum API)
80
- └── package.json
81
- ```
82
-
83
- ### API template (`--template api`)
84
-
85
- ```
86
- my-api-app/
87
- ├── controllers/
88
- │ └── usersController.js
89
- ├── middlewares/
90
- │ └── authMock.js
91
- ├── routes.js
92
- ├── app.js
93
- └── package.json
94
- ```
95
-
96
- ---
97
-
98
- ## 🧩 Core API
99
-
100
- > Kaelum exposes a factory — use `require('kaelum')` and call it to get an app instance:
101
-
102
- ```js
103
- const kaelum = require("kaelum");
104
- const app = kaelum();
105
- ```
106
-
107
- ### `app.setConfig(options)`
108
-
109
- Enable/disable common features:
110
-
111
- ```js
112
- app.setConfig({
113
- cors: true, // apply CORS (requires cors package in dependencies)
114
- helmet: true, // apply Helmet
115
- static: "public", // serve static files from "public"
116
- bodyParser: true, // default: enabled (JSON + urlencoded)
117
- logs: false, // enable request logging via morgan (if installed)
118
- port: 3000, // prefered port (used when calling app.start() without port)
119
- });
120
- ```
121
-
122
- - `setConfig` persists settings to the Kaelum config and will install/remove Kaelum-managed middlewares.
123
- - Kaelum enables JSON/urlencoded parsing by default so beginners won't forget to parse request bodies.
124
-
125
- ---
126
-
127
- ### `app.start(port, callback)`
128
-
129
- Starts the HTTP server. If `port` is omitted, Kaelum reads `port` from `setConfig` or falls back to `3000`.
130
-
131
- ```js
132
- app.start(3000, () => console.log("Running"));
133
- ```
134
-
135
- ---
136
-
137
- ### `app.addRoute(path, handlers)` and `app.apiRoute(resource, handlers)`
138
-
139
- Register routes easily:
140
-
141
- ```js
142
- app.addRoute("/home", {
143
- get: (req, res) => res.send("Welcome!"),
144
- post: (req, res) => res.send("Posted!"),
145
- });
146
-
147
- // apiRoute builds RESTy resources with nested subpaths:
148
- app.apiRoute("users", {
149
- get: listUsers,
150
- post: createUser,
151
- "/:id": {
152
- get: getUserById,
153
- put: updateUser,
154
- delete: deleteUser,
155
- },
156
- });
157
- ```
158
-
159
- `addRoute` also accepts a single handler function (assumed `GET`).
160
-
161
- ---
162
-
163
- ### `app.setMiddleware(...)`
164
-
165
- Flexible helper to register middleware(s):
166
-
167
- ```js
168
- // single middleware
169
- app.setMiddleware(require("helmet")());
170
-
171
- // array of middlewares
172
- app.setMiddleware([mw1, mw2]);
173
-
174
- // mount middleware on a path
175
- app.setMiddleware("/admin", authMiddleware);
176
- ```
177
-
178
- ---
179
-
180
- ### `app.redirect(from, to, status)`
181
-
182
- Register a redirect route:
183
-
184
- ```js
185
- app.redirect("/old-url", "/new-url", 302);
186
- ```
187
-
188
- ---
189
-
190
- ### `app.healthCheck(path = '/health')`
191
-
192
- Adds a health endpoint returning `{ status: 'OK', uptime, timestamp, pid }`.
193
-
194
- ---
195
-
196
- ### `app.useErrorHandler(options)`
197
-
198
- Attach Kaelum's default JSON error handler:
199
-
200
- ```js
201
- app.useErrorHandler({ exposeStack: false });
202
- ```
203
-
204
- It will return standardized JSON for errors and log server-side errors (5xx) to `console.error`.
205
-
206
- ---
207
-
208
- ## 🔧 Local development & contributing
209
-
210
- ```bash
211
- git clone https://github.com/MatheusCampagnolo/kaelum.git
212
- cd kaelum
213
- npm install
214
- npm link
215
- ```
216
-
217
- Now you can test the CLI locally:
218
-
219
- ```bash
220
- npx kaelum create my-test --template web
221
- ```
222
-
223
- ---
224
-
225
- ## 📝 Why Kaelum?
226
-
227
- - Reduces repetitive boilerplate required to start Node/Express web projects.
228
- - Opinionated scaffolding (MVC) helps beginners adopt better structure.
229
- - Keeps a small API surface: easy to teach and document.
230
- - Extensible — `setConfig` and middleware helpers allow adding features without exposing Express internals.
231
-
232
- ---
233
-
234
- ## ✅ Current status
235
-
236
- > Kaelum is under active development.
237
- > CLI scaffolds web and API templates, and the framework includes the MVP helpers (`start`, `addRoute`, `apiRoute`, `setConfig`, `static`, `redirect`, `healthCheck`, `useErrorHandler`) and security toggles for `cors` and `helmet`.
238
-
239
- ---
240
-
241
- ## 📚 Links
242
-
243
- - [GitHub](https://github.com/MatheusCampagnolo/kaelum)
244
- - [npm](https://www.npmjs.com/package/kaelum)
245
- - [Documentation](https://matheuscampagnolo.github.io/kaelum/)
246
-
247
- ---
248
-
249
- ## 🧾 License
250
-
251
- MIT — see [LICENSE](LICENSE).
252
-
253
- ---
254
-
255
- ## ✍️ Notes for maintainers
256
-
257
- - Templates use `commonjs` (`require` / `module.exports`).
258
- - Update template dependencies to reference the correct Kaelum version when releasing new npm versions.
1
+ <div align="center">
2
+
3
+ <h1>Kaelum</h1>
4
+
5
+ [![npm version](https://img.shields.io/npm/v/kaelum)](https://www.npmjs.com/package/kaelum)
6
+ [![Build Status](https://github.com/MatheusCampagnolo/kaelum/actions/workflows/deploy-docs.yml/badge.svg)](https://github.com/MatheusCampagnolo/kaelum/actions)
7
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
8
+ [![Docs](https://img.shields.io/badge/docs-online-blue)](https://matheuscampagnolo.github.io/kaelum/)
9
+
10
+ **Kaelum.js** — Minimalist Node.js framework to simplify creation of web pages and REST APIs.
11
+ Designed for students and developers who want a fast, opinionated project scaffold and a small, friendly API that encapsulates common Express.js boilerplate.
12
+
13
+ 👉 [**Read the full documentation here**](https://matheuscampagnolo.github.io/kaelum/)
14
+
15
+ **If Kaelum helps you, consider supporting its development:**
16
+
17
+ <a href='https://ko-fi.com/Z8Z51NK4KT' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
18
+
19
+ </div>
20
+
21
+ ## 🚀 Quick start
22
+
23
+ Create a new project (interactive):
24
+
25
+ ```bash
26
+ npx kaelum create
27
+ ```
28
+
29
+ Or create non-interactively (project name + template):
30
+
31
+ ```bash
32
+ npx kaelum create my-app --template web
33
+ # or
34
+ npx kaelum create my-api --template api
35
+ ```
36
+
37
+ Then:
38
+
39
+ ```bash
40
+ cd my-app
41
+ npm install
42
+ npm start
43
+ ```
44
+
45
+ > No need to install Kaelum globally — `npx` handles execution.
46
+
47
+ ---
48
+
49
+ ## 📦 What Kaelum provides
50
+
51
+ - CLI that scaffolds a ready-to-run project (Web or API template) using an opinionated **MVC** structure.
52
+ - Thin abstraction layer over **Express.js** that:
53
+
54
+ - automates JSON / URL-encoded parsing by default,
55
+ - automatically configures common security middlewares via `setConfig` (CORS, Helmet),
56
+ - exposes a small, easy-to-learn API for routes, middleware and configuration.
57
+
58
+ - Small set of helpers for common tasks: `start`, `addRoute`, `apiRoute`, `setConfig`, `static`, `redirect`, `healthCheck`, `useErrorHandler`, and more.
59
+
60
+ Kaelum aims to reduce the initial setup burden while keeping flexibility for advanced users.
61
+
62
+ ---
63
+
64
+ ## 📁 Template structures
65
+
66
+ ### Web template (`--template web`)
67
+
68
+ ```
69
+ my-web-app/
70
+ ├── public/ # Static files (CSS, JS)
71
+ │ └── style.css
72
+ ├── views/ # HTML templates
73
+ │ └── index.html
74
+ ├── controllers/ # Controller logic (MVC)
75
+ │ └── .gitkeep
76
+ ├── middlewares/ # Custom middlewares
77
+ │ └── logger.js
78
+ ├── routes.js # Route definitions (example uses Kaelum helpers)
79
+ ├── app.js # Server initialization (uses Kaelum API)
80
+ └── package.json
81
+ ```
82
+
83
+ ### API template (`--template api`)
84
+
85
+ ```
86
+ my-api-app/
87
+ ├── controllers/
88
+ │ └── usersController.js
89
+ ├── middlewares/
90
+ │ └── authMock.js
91
+ ├── routes.js
92
+ ├── app.js
93
+ └── package.json
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 🧩 Core API
99
+
100
+ > Kaelum exposes a factory — use `require('kaelum')` and call it to get an app instance:
101
+
102
+ ```js
103
+ const kaelum = require("kaelum");
104
+ const app = kaelum();
105
+ ```
106
+
107
+ ### `app.setConfig(options)`
108
+
109
+ Enable/disable common features:
110
+
111
+ ```js
112
+ app.setConfig({
113
+ cors: true, // apply CORS (requires cors package in dependencies)
114
+ helmet: true, // apply Helmet
115
+ static: "public", // serve static files from "public"
116
+ bodyParser: true, // default: enabled (JSON + urlencoded)
117
+ logs: false, // enable request logging via morgan (if installed)
118
+ port: 3000, // prefered port (used when calling app.start() without port)
119
+ });
120
+ ```
121
+
122
+ - `setConfig` persists settings to the Kaelum config and will install/remove Kaelum-managed middlewares.
123
+ - Kaelum enables JSON/urlencoded parsing by default so beginners won't forget to parse request bodies.
124
+
125
+ ---
126
+
127
+ ### `app.start(port, callback)`
128
+
129
+ Starts the HTTP server. If `port` is omitted, Kaelum reads `port` from `setConfig` or falls back to `3000`.
130
+
131
+ ```js
132
+ app.start(3000, () => console.log("Running"));
133
+ ```
134
+
135
+ ---
136
+
137
+ ### `app.addRoute(path, handlers)` and `app.apiRoute(resource, handlers)`
138
+
139
+ Register routes easily:
140
+
141
+ ```js
142
+ app.addRoute("/home", {
143
+ get: (req, res) => res.send("Welcome!"),
144
+ post: (req, res) => res.send("Posted!"),
145
+ });
146
+
147
+ // apiRoute builds RESTy resources with nested subpaths:
148
+ app.apiRoute("users", {
149
+ get: listUsers,
150
+ post: createUser,
151
+ "/:id": {
152
+ get: getUserById,
153
+ put: updateUser,
154
+ delete: deleteUser,
155
+ },
156
+ });
157
+ ```
158
+
159
+ `addRoute` also accepts a single handler function (assumed `GET`).
160
+
161
+ ---
162
+
163
+ ### `app.setMiddleware(...)`
164
+
165
+ Flexible helper to register middleware(s):
166
+
167
+ ```js
168
+ // single middleware
169
+ app.setMiddleware(require("helmet")());
170
+
171
+ // array of middlewares
172
+ app.setMiddleware([mw1, mw2]);
173
+
174
+ // mount middleware on a path
175
+ app.setMiddleware("/admin", authMiddleware);
176
+ ```
177
+
178
+ ---
179
+
180
+ ### `app.redirect(from, to, status)`
181
+
182
+ Register a redirect route:
183
+
184
+ ```js
185
+ app.redirect("/old-url", "/new-url", 302);
186
+ ```
187
+
188
+ ---
189
+
190
+ ### `app.healthCheck(path = '/health')`
191
+
192
+ Adds a health endpoint returning `{ status: 'OK', uptime, timestamp, pid }`.
193
+
194
+ ---
195
+
196
+ ### `app.useErrorHandler(options)`
197
+
198
+ Attach Kaelum's default JSON error handler:
199
+
200
+ ```js
201
+ app.useErrorHandler({ exposeStack: false });
202
+ ```
203
+
204
+ It will return standardized JSON for errors and log server-side errors (5xx) to `console.error`.
205
+
206
+ ---
207
+
208
+ ## 🔧 Local development & contributing
209
+
210
+ ```bash
211
+ git clone https://github.com/MatheusCampagnolo/kaelum.git
212
+ cd kaelum
213
+ npm install
214
+ npm link
215
+ ```
216
+
217
+ Now you can test the CLI locally:
218
+
219
+ ```bash
220
+ npx kaelum create my-test --template web
221
+ ```
222
+
223
+ ---
224
+
225
+ ## 📝 Why Kaelum?
226
+
227
+ - Reduces repetitive boilerplate required to start Node/Express web projects.
228
+ - Opinionated scaffolding (MVC) helps beginners adopt better structure.
229
+ - Keeps a small API surface: easy to teach and document.
230
+ - Extensible — `setConfig` and middleware helpers allow adding features without exposing Express internals.
231
+
232
+ ---
233
+
234
+ ## ✅ Current status
235
+
236
+ > Kaelum is under active development.
237
+ > CLI scaffolds web and API templates, and the framework includes the MVP helpers (`start`, `addRoute`, `apiRoute`, `setConfig`, `static`, `redirect`, `healthCheck`, `useErrorHandler`) and security toggles for `cors` and `helmet`.
238
+
239
+ ---
240
+
241
+ ## 📚 Links
242
+
243
+ - [GitHub](https://github.com/MatheusCampagnolo/kaelum)
244
+ - [npm](https://www.npmjs.com/package/kaelum)
245
+ - [Documentation](https://matheuscampagnolo.github.io/kaelum/)
246
+
247
+ ---
248
+
249
+ ## 🧾 License
250
+
251
+ MIT — see [LICENSE](LICENSE).
252
+
253
+ ---
254
+
255
+ ## ✍️ Notes for maintainers
256
+
257
+ - Templates use `commonjs` (`require` / `module.exports`).
258
+ - Update template dependencies to reference the correct Kaelum version when releasing new npm versions.
package/core/setConfig.js CHANGED
@@ -1,255 +1,255 @@
1
- // core/setConfig.js
2
- // Kaelum centralized configuration helper.
3
- // - Supports toggling CORS, Helmet, static folder, Morgan logs, bodyParser, and port.
4
- // - Persists merged config to app locals (app.set("kaelum:config", ...)).
5
- // - Keeps references to Kaelum-installed middleware so toggles (false) remove them.
6
-
7
- const path = require("path");
8
-
9
- function tryRequire(name) {
10
- try {
11
- return require(name);
12
- } catch (e) {
13
- return null;
14
- }
15
- }
16
-
17
- /**
18
- * Merge new options into existing stored config
19
- * @param {Object} app
20
- * @param {Object} options
21
- */
22
- function persistConfig(app, options = {}) {
23
- const prev = app.locals.kaelumConfig || {};
24
- const merged = Object.assign({}, prev, options);
25
- app.locals.kaelumConfig = merged;
26
- app.set("kaelum:config", merged);
27
- return merged;
28
- }
29
-
30
- /**
31
- * Remove a middleware function reference from express stack
32
- * @param {Object} app
33
- * @param {Function} fn
34
- */
35
- function removeMiddlewareByFn(app, fn) {
36
- if (!app || !app._router || !Array.isArray(app._router.stack)) return;
37
- app._router.stack = app._router.stack.filter((layer) => layer.handle !== fn);
38
- }
39
-
40
- /**
41
- * Remove static middleware previously installed by Kaelum (if any)
42
- * @param {Object} app
43
- */
44
- function removeKaelumStatic(app) {
45
- const prev = app.locals && app.locals._kaelum_static;
46
- if (prev) {
47
- removeMiddlewareByFn(app, prev);
48
- app.locals._kaelum_static = null;
49
- }
50
- }
51
-
52
- /**
53
- * Remove body parsers previously installed by Kaelum
54
- * @param {Object} app
55
- */
56
- function removeKaelumBodyParsers(app) {
57
- const arr = app.locals && app.locals._kaelum_bodyparsers;
58
- if (Array.isArray(arr)) {
59
- arr.forEach((fn) => removeMiddlewareByFn(app, fn));
60
- app.locals._kaelum_bodyparsers = [];
61
- }
62
- }
63
-
64
- /**
65
- * Remove morgan logger if previously set
66
- * @param {Object} app
67
- */
68
- function removeKaelumLogger(app) {
69
- const prev = app.locals && app.locals._kaelum_logger;
70
- if (prev) {
71
- removeMiddlewareByFn(app, prev);
72
- app.locals._kaelum_logger = null;
73
- }
74
- }
75
-
76
- /**
77
- * Remove Kaelum-installed CORS middleware (if any)
78
- * @param {Object} app
79
- */
80
- function removeKaelumCors(app) {
81
- const prev = app.locals && app.locals._kaelum_cors;
82
- if (prev) {
83
- removeMiddlewareByFn(app, prev);
84
- app.locals._kaelum_cors = null;
85
- }
86
- }
87
-
88
- /**
89
- * Remove Kaelum-installed Helmet middleware (if any)
90
- * @param {Object} app
91
- */
92
- function removeKaelumHelmet(app) {
93
- const prev = app.locals && app.locals._kaelum_helmet;
94
- if (prev) {
95
- removeMiddlewareByFn(app, prev);
96
- app.locals._kaelum_helmet = null;
97
- }
98
- }
99
-
100
- /**
101
- * Apply configuration options to the app
102
- * @param {Object} app - express app instance
103
- * @param {Object} options - supported keys: cors, helmet, static, logs, port, bodyParser
104
- */
105
- function setConfig(app, options = {}) {
106
- if (!app) throw new Error("setConfig requires an app instance");
107
-
108
- // persist/merge config
109
- const cfg = persistConfig(app, options);
110
-
111
- // --- CORS ---
112
- if (options.hasOwnProperty("cors")) {
113
- if (options.cors) {
114
- const cors = tryRequire("cors");
115
- const corsOpts = options.cors === true ? {} : options.cors;
116
- if (!cors) {
117
- console.warn(
118
- "Kaelum: cors package not installed. Skipping CORS setup."
119
- );
120
- } else {
121
- // remove previous Kaelum-installed cors if exists
122
- removeKaelumCors(app);
123
-
124
- // create middleware function and store reference so it can be removed later
125
- const corsFn = cors(corsOpts);
126
- app.locals._kaelum_cors = corsFn;
127
- app.use(corsFn);
128
- console.log("🛡️ CORS activated.");
129
- }
130
- } else {
131
- // disable Kaelum-installed CORS middleware if present
132
- removeKaelumCors(app);
133
- console.log("🛡️ CORS disabled (Kaelum-managed).");
134
- }
135
- }
136
-
137
- // --- Helmet ---
138
- if (options.hasOwnProperty("helmet")) {
139
- if (options.helmet) {
140
- const helmet = tryRequire("helmet");
141
- const helmetOpts = options.helmet === true ? {} : options.helmet;
142
- if (!helmet) {
143
- console.warn(
144
- "Kaelum: helmet package not installed. Skipping Helmet setup."
145
- );
146
- } else {
147
- // remove previous Kaelum-installed helmet if exists
148
- removeKaelumHelmet(app);
149
-
150
- const helmetFn = helmet(helmetOpts);
151
- app.locals._kaelum_helmet = helmetFn;
152
- app.use(helmetFn);
153
- console.log("🛡️ Helmet activated.");
154
- }
155
- } else {
156
- // disable Kaelum-installed Helmet middleware if present
157
- removeKaelumHelmet(app);
158
- console.log("🛡️ Helmet disabled (Kaelum-managed).");
159
- }
160
- }
161
-
162
- // --- Static folder handling ---
163
- if (options.hasOwnProperty("static")) {
164
- // remove previous Kaelum static
165
- removeKaelumStatic(app);
166
-
167
- if (options.static) {
168
- const expressStatic =
169
- tryRequire("express").static || require("express").static;
170
- // resolve to absolute path relative to project root if necessary
171
- const dir =
172
- typeof options.static === "string"
173
- ? path.resolve(process.cwd(), options.static)
174
- : path.join(process.cwd(), "public");
175
- const staticFn = expressStatic(dir);
176
- app.locals._kaelum_static = staticFn;
177
- app.use(staticFn);
178
- console.log(`📁 Static files served from ${dir}`);
179
- } else {
180
- // static === false -> nothing to add (static removed)
181
- console.log("📁 Static serving disabled.");
182
- }
183
- }
184
-
185
- // --- Body parser toggle ---
186
- if (options.hasOwnProperty("bodyParser")) {
187
- if (options.bodyParser === false) {
188
- // remove Kaelum-installed body parsers
189
- removeKaelumBodyParsers(app);
190
- console.log("📦 Body parsers disabled.");
191
- } else {
192
- // ensure body parsers are installed (if not present)
193
- if (
194
- !app.locals._kaelum_bodyparsers ||
195
- app.locals._kaelum_bodyparsers.length === 0
196
- ) {
197
- const jsonParser = tryRequire("express").json();
198
- const urlencodedParser = tryRequire("express").urlencoded({
199
- extended: true,
200
- });
201
- app.locals._kaelum_bodyparsers = [jsonParser, urlencodedParser];
202
- app.use(jsonParser);
203
- app.use(urlencodedParser);
204
- console.log("📦 Body parsers enabled (JSON + URL-encoded).");
205
- }
206
- }
207
- }
208
-
209
- // --- Logs (morgan) ---
210
- if (options.hasOwnProperty("logs")) {
211
- // remove previous logger first
212
- removeKaelumLogger(app);
213
-
214
- if (options.logs) {
215
- const morgan = tryRequire("morgan");
216
- if (!morgan) {
217
- console.warn("Kaelum: morgan package not installed. Skipping logs.");
218
- } else {
219
- // simple dev format by default; could be configured
220
- const logger = morgan("dev");
221
- app.locals._kaelum_logger = logger;
222
- app.use(logger);
223
- console.log("📊 Request logging enabled (morgan).");
224
- }
225
- } else {
226
- console.log("📊 Request logging disabled.");
227
- }
228
- }
229
-
230
- // --- Port persisted in config (start will read it) ---
231
- if (options.hasOwnProperty("port")) {
232
- const p = options.port;
233
- if (p === false || p === null) {
234
- // unset
235
- const merged = Object.assign({}, app.locals.kaelumConfig);
236
- delete merged.port;
237
- app.locals.kaelumConfig = merged;
238
- app.set("kaelum:config", merged);
239
- console.log("🔌 Port preference cleared from Kaelum config.");
240
- } else if (typeof p === "number" || typeof p === "string") {
241
- // persist port as number if possible
242
- const asNum = Number(p);
243
- app.locals.kaelumConfig.port = Number.isNaN(asNum) ? p : asNum;
244
- app.set("kaelum:config", app.locals.kaelumConfig);
245
- console.log(
246
- `🔌 Port set to ${app.locals.kaelumConfig.port} in Kaelum config.`
247
- );
248
- }
249
- }
250
-
251
- // Return the full merged config for convenience
252
- return app.locals.kaelumConfig;
253
- }
254
-
1
+ // core/setConfig.js
2
+ // Kaelum centralized configuration helper.
3
+ // - Supports toggling CORS, Helmet, static folder, Morgan logs, bodyParser, and port.
4
+ // - Persists merged config to app locals (app.set("kaelum:config", ...)).
5
+ // - Keeps references to Kaelum-installed middleware so toggles (false) remove them.
6
+
7
+ const path = require("path");
8
+
9
+ function tryRequire(name) {
10
+ try {
11
+ return require(name);
12
+ } catch (e) {
13
+ return null;
14
+ }
15
+ }
16
+
17
+ /**
18
+ * Merge new options into existing stored config
19
+ * @param {Object} app
20
+ * @param {Object} options
21
+ */
22
+ function persistConfig(app, options = {}) {
23
+ const prev = app.locals.kaelumConfig || {};
24
+ const merged = Object.assign({}, prev, options);
25
+ app.locals.kaelumConfig = merged;
26
+ app.set("kaelum:config", merged);
27
+ return merged;
28
+ }
29
+
30
+ /**
31
+ * Remove a middleware function reference from express stack
32
+ * @param {Object} app
33
+ * @param {Function} fn
34
+ */
35
+ function removeMiddlewareByFn(app, fn) {
36
+ if (!app || !app._router || !Array.isArray(app._router.stack)) return;
37
+ app._router.stack = app._router.stack.filter((layer) => layer.handle !== fn);
38
+ }
39
+
40
+ /**
41
+ * Remove static middleware previously installed by Kaelum (if any)
42
+ * @param {Object} app
43
+ */
44
+ function removeKaelumStatic(app) {
45
+ const prev = app.locals && app.locals._kaelum_static;
46
+ if (prev) {
47
+ removeMiddlewareByFn(app, prev);
48
+ app.locals._kaelum_static = null;
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Remove body parsers previously installed by Kaelum
54
+ * @param {Object} app
55
+ */
56
+ function removeKaelumBodyParsers(app) {
57
+ const arr = app.locals && app.locals._kaelum_bodyparsers;
58
+ if (Array.isArray(arr)) {
59
+ arr.forEach((fn) => removeMiddlewareByFn(app, fn));
60
+ app.locals._kaelum_bodyparsers = [];
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Remove morgan logger if previously set
66
+ * @param {Object} app
67
+ */
68
+ function removeKaelumLogger(app) {
69
+ const prev = app.locals && app.locals._kaelum_logger;
70
+ if (prev) {
71
+ removeMiddlewareByFn(app, prev);
72
+ app.locals._kaelum_logger = null;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Remove Kaelum-installed CORS middleware (if any)
78
+ * @param {Object} app
79
+ */
80
+ function removeKaelumCors(app) {
81
+ const prev = app.locals && app.locals._kaelum_cors;
82
+ if (prev) {
83
+ removeMiddlewareByFn(app, prev);
84
+ app.locals._kaelum_cors = null;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Remove Kaelum-installed Helmet middleware (if any)
90
+ * @param {Object} app
91
+ */
92
+ function removeKaelumHelmet(app) {
93
+ const prev = app.locals && app.locals._kaelum_helmet;
94
+ if (prev) {
95
+ removeMiddlewareByFn(app, prev);
96
+ app.locals._kaelum_helmet = null;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Apply configuration options to the app
102
+ * @param {Object} app - express app instance
103
+ * @param {Object} options - supported keys: cors, helmet, static, logs, port, bodyParser
104
+ */
105
+ function setConfig(app, options = {}) {
106
+ if (!app) throw new Error("setConfig requires an app instance");
107
+
108
+ // persist/merge config
109
+ const cfg = persistConfig(app, options);
110
+
111
+ // --- CORS ---
112
+ if (options.hasOwnProperty("cors")) {
113
+ if (options.cors) {
114
+ const cors = tryRequire("cors");
115
+ const corsOpts = options.cors === true ? {} : options.cors;
116
+ if (!cors) {
117
+ console.warn(
118
+ "Kaelum: cors package not installed. Skipping CORS setup."
119
+ );
120
+ } else {
121
+ // remove previous Kaelum-installed cors if exists
122
+ removeKaelumCors(app);
123
+
124
+ // create middleware function and store reference so it can be removed later
125
+ const corsFn = cors(corsOpts);
126
+ app.locals._kaelum_cors = corsFn;
127
+ app.use(corsFn);
128
+ console.log("🛡️ CORS activated.");
129
+ }
130
+ } else {
131
+ // disable Kaelum-installed CORS middleware if present
132
+ removeKaelumCors(app);
133
+ console.log("🛡️ CORS disabled (Kaelum-managed).");
134
+ }
135
+ }
136
+
137
+ // --- Helmet ---
138
+ if (options.hasOwnProperty("helmet")) {
139
+ if (options.helmet) {
140
+ const helmet = tryRequire("helmet");
141
+ const helmetOpts = options.helmet === true ? {} : options.helmet;
142
+ if (!helmet) {
143
+ console.warn(
144
+ "Kaelum: helmet package not installed. Skipping Helmet setup."
145
+ );
146
+ } else {
147
+ // remove previous Kaelum-installed helmet if exists
148
+ removeKaelumHelmet(app);
149
+
150
+ const helmetFn = helmet(helmetOpts);
151
+ app.locals._kaelum_helmet = helmetFn;
152
+ app.use(helmetFn);
153
+ console.log("🛡️ Helmet activated.");
154
+ }
155
+ } else {
156
+ // disable Kaelum-installed Helmet middleware if present
157
+ removeKaelumHelmet(app);
158
+ console.log("🛡️ Helmet disabled (Kaelum-managed).");
159
+ }
160
+ }
161
+
162
+ // --- Static folder handling ---
163
+ if (options.hasOwnProperty("static")) {
164
+ // remove previous Kaelum static
165
+ removeKaelumStatic(app);
166
+
167
+ if (options.static) {
168
+ const expressStatic =
169
+ tryRequire("express").static || require("express").static;
170
+ // resolve to absolute path relative to project root if necessary
171
+ const dir =
172
+ typeof options.static === "string"
173
+ ? path.resolve(process.cwd(), options.static)
174
+ : path.join(process.cwd(), "public");
175
+ const staticFn = expressStatic(dir);
176
+ app.locals._kaelum_static = staticFn;
177
+ app.use(staticFn);
178
+ console.log(`📁 Static files served from ${dir}`);
179
+ } else {
180
+ // static === false -> nothing to add (static removed)
181
+ console.log("📁 Static serving disabled.");
182
+ }
183
+ }
184
+
185
+ // --- Body parser toggle ---
186
+ if (options.hasOwnProperty("bodyParser")) {
187
+ if (options.bodyParser === false) {
188
+ // remove Kaelum-installed body parsers
189
+ removeKaelumBodyParsers(app);
190
+ console.log("📦 Body parsers disabled.");
191
+ } else {
192
+ // ensure body parsers are installed (if not present)
193
+ if (
194
+ !app.locals._kaelum_bodyparsers ||
195
+ app.locals._kaelum_bodyparsers.length === 0
196
+ ) {
197
+ const jsonParser = tryRequire("express").json();
198
+ const urlencodedParser = tryRequire("express").urlencoded({
199
+ extended: true,
200
+ });
201
+ app.locals._kaelum_bodyparsers = [jsonParser, urlencodedParser];
202
+ app.use(jsonParser);
203
+ app.use(urlencodedParser);
204
+ console.log("📦 Body parsers enabled (JSON + URL-encoded).");
205
+ }
206
+ }
207
+ }
208
+
209
+ // --- Logs (morgan) ---
210
+ if (options.hasOwnProperty("logs")) {
211
+ // remove previous logger first
212
+ removeKaelumLogger(app);
213
+
214
+ if (options.logs) {
215
+ const morgan = tryRequire("morgan");
216
+ if (!morgan) {
217
+ console.warn("Kaelum: morgan package not installed. Skipping logs.");
218
+ } else {
219
+ // simple dev format by default; could be configured
220
+ const logger = morgan("dev");
221
+ app.locals._kaelum_logger = logger;
222
+ app.use(logger);
223
+ console.log("📊 Request logging enabled (morgan).");
224
+ }
225
+ } else {
226
+ console.log("📊 Request logging disabled.");
227
+ }
228
+ }
229
+
230
+ // --- Port persisted in config (start will read it) ---
231
+ if (options.hasOwnProperty("port")) {
232
+ const p = options.port;
233
+ if (p === false || p === null) {
234
+ // unset
235
+ const merged = Object.assign({}, app.locals.kaelumConfig);
236
+ delete merged.port;
237
+ app.locals.kaelumConfig = merged;
238
+ app.set("kaelum:config", merged);
239
+ console.log("🔌 Port preference cleared from Kaelum config.");
240
+ } else if (typeof p === "number" || typeof p === "string") {
241
+ // persist port as number if possible
242
+ const asNum = Number(p);
243
+ app.locals.kaelumConfig.port = Number.isNaN(asNum) ? p : asNum;
244
+ app.set("kaelum:config", app.locals.kaelumConfig);
245
+ console.log(
246
+ `🔌 Port set to ${app.locals.kaelumConfig.port} in Kaelum config.`
247
+ );
248
+ }
249
+ }
250
+
251
+ // Return the full merged config for convenience
252
+ return app.locals.kaelumConfig;
253
+ }
254
+
255
255
  module.exports = setConfig;
package/core/start.js CHANGED
@@ -89,7 +89,7 @@ function start(app, port, cb) {
89
89
  let server;
90
90
  try {
91
91
  server = app.listen(usePort, () => {
92
- console.log(`🚀 Kaelum server running on port ${usePort}`);
92
+ console.log(`🚀 Kaelum server running at http://localhost:${usePort}`);
93
93
  if (typeof cb === "function") cb();
94
94
  });
95
95
  } catch (err) {
package/createApp.js CHANGED
@@ -20,6 +20,9 @@ const redirect = require("./core/redirect");
20
20
 
21
21
  function createApp() {
22
22
  const app = express();
23
+
24
+ // Security: disable x-powered-by header to obfuscate server details
25
+ app.disable("x-powered-by");
23
26
 
24
27
  // ensure locals object and initial persisted config
25
28
  app.locals = app.locals || {};
@@ -43,6 +46,11 @@ function createApp() {
43
46
  app.use(jsonParser);
44
47
  app.use(urlencodedParser);
45
48
 
49
+ // --- View Engine (EJS) ---
50
+ // Set EJS as the default view engine and point to ./views
51
+ app.set("view engine", "ejs");
52
+ app.set("views", "./views");
53
+
46
54
  // --- wrapper for core.setConfig ---
47
55
  app.setConfig = function (options = {}) {
48
56
  // call core setConfig if available (it should persist merged config)
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "kaelum",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "A minimalist Node.js framework for building web pages and APIs with simplicity and speed.",
5
5
  "main": "index.js",
6
6
  "exports": {
7
7
  ".": "./index.js"
8
8
  },
9
9
  "bin": {
10
- "kaelum": "./cli/index.js"
10
+ "kaelum": "cli/index.js"
11
11
  },
12
12
  "scripts": {
13
13
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -27,10 +27,11 @@
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "cors": "^2.8.5",
30
+ "ejs": "^3.1.10",
30
31
  "express": "^4.18.2",
31
32
  "fs-extra": "^11.3.0",
32
33
  "helmet": "^7.2.0",
33
34
  "inquirer": "^12.6.0",
34
35
  "morgan": "^1.10.1"
35
36
  }
36
- }
37
+ }