kaelum 1.1.0 β 1.3.0
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 +167 -53
- package/cli/create.js +70 -37
- package/cli/index.js +49 -7
- package/cli/templates/api/app.js +26 -0
- package/cli/templates/api/controllers/usersController.js +58 -0
- package/cli/templates/api/middlewares/authMock.js +13 -0
- package/cli/templates/api/package.json +24 -0
- package/cli/templates/api/routes.js +34 -0
- package/cli/templates/web/app.js +15 -4
- package/cli/templates/web/middlewares/logger.js +5 -5
- package/cli/templates/web/package.json +17 -7
- package/cli/templates/web/public/style.css +42 -35
- package/cli/templates/web/routes.js +22 -17
- package/cli/templates/web/views/index.html +39 -19
- package/cli/utils.js +50 -4
- package/core/addRoute.js +156 -5
- package/core/apiRoute.js +135 -0
- package/core/errorHandler.js +139 -0
- package/core/healthCheck.js +204 -0
- package/core/redirect.js +177 -0
- package/core/setConfig.js +245 -20
- package/core/setMiddleware.js +183 -6
- package/core/start.js +111 -4
- package/createApp.js +166 -13
- package/package.json +4 -3
- package/bin/.gitkeep +0 -0
- package/cli/templates/api/.gitkeep +0 -0
- package/utils/.gitkeep +0 -0
package/README.md
CHANGED
|
@@ -1,134 +1,248 @@
|
|
|
1
1
|
# Kaelum
|
|
2
2
|
|
|
3
|
-
**Kaelum**
|
|
3
|
+
**Kaelum.JS** β Minimalist Node.js framework to simplify creation of web pages and REST APIs.
|
|
4
|
+
Designed for students and developers who want a fast, opinionated project scaffold and a small, friendly API that encapsulates common Express.js boilerplate.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## π Quick start
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
Create a new project (interactive):
|
|
8
11
|
|
|
9
12
|
```bash
|
|
10
13
|
npx kaelum create
|
|
11
14
|
````
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
Or create non-interactively (project name + template):
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
```bash
|
|
19
|
+
npx kaelum create my-app --template web
|
|
20
|
+
# or
|
|
21
|
+
npx kaelum create my-api --template api
|
|
22
|
+
```
|
|
19
23
|
|
|
20
|
-
Then
|
|
24
|
+
Then:
|
|
21
25
|
|
|
22
26
|
```bash
|
|
23
|
-
cd my-
|
|
27
|
+
cd my-app
|
|
24
28
|
npm install
|
|
25
29
|
npm start
|
|
26
30
|
```
|
|
27
31
|
|
|
28
|
-
>
|
|
32
|
+
> No need to install Kaelum globally β `npx` handles execution.
|
|
29
33
|
|
|
30
34
|
---
|
|
31
35
|
|
|
32
|
-
##
|
|
36
|
+
## π¦ What Kaelum provides
|
|
33
37
|
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
*
|
|
38
|
+
* CLI that scaffolds a ready-to-run project (Web or API template) using an opinionated **MVC** structure.
|
|
39
|
+
* Thin abstraction layer over **Express.js** that:
|
|
40
|
+
|
|
41
|
+
* automates JSON / URL-encoded parsing by default,
|
|
42
|
+
* automatically configures common security middlewares via `setConfig` (CORS, Helmet),
|
|
43
|
+
* exposes a small, easy-to-learn API for routes, middleware and configuration.
|
|
44
|
+
* Small set of helpers for common tasks: `start`, `addRoute`, `apiRoute`, `setConfig`, `static`, `redirect`, `healthCheck`, `useErrorHandler`, and more.
|
|
45
|
+
|
|
46
|
+
Kaelum aims to reduce the initial setup burden while keeping flexibility for advanced users.
|
|
39
47
|
|
|
40
48
|
---
|
|
41
49
|
|
|
42
|
-
## π
|
|
50
|
+
## π Template structures
|
|
43
51
|
|
|
44
|
-
|
|
52
|
+
### Web template (created by `npx kaelum create <name>` with template `web`)
|
|
45
53
|
|
|
46
54
|
```
|
|
47
55
|
my-web-app/
|
|
48
|
-
βββ public/ # Static files (
|
|
56
|
+
βββ public/ # Static files (CSS, JS)
|
|
49
57
|
β βββ style.css
|
|
50
58
|
βββ views/ # HTML templates
|
|
51
59
|
β βββ index.html
|
|
52
|
-
βββ controllers/ #
|
|
60
|
+
βββ controllers/ # Controller logic (MVC)
|
|
53
61
|
β βββ .gitkeep
|
|
54
62
|
βββ middlewares/ # Custom middlewares
|
|
55
|
-
β βββ
|
|
56
|
-
βββ routes.js # Route definitions
|
|
57
|
-
βββ app.js # Server initialization
|
|
58
|
-
βββ package.json
|
|
63
|
+
β βββ logger.js
|
|
64
|
+
βββ routes.js # Route definitions (example uses Kaelum helpers)
|
|
65
|
+
βββ app.js # Server initialization (uses Kaelum API)
|
|
66
|
+
βββ package.json
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### API template (`--template api`)
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
my-api-app/
|
|
73
|
+
βββ controllers/
|
|
74
|
+
β βββ usersController.js
|
|
75
|
+
βββ middlewares/
|
|
76
|
+
β βββ authMock.js
|
|
77
|
+
βββ routes.js
|
|
78
|
+
βββ app.js
|
|
79
|
+
βββ package.json
|
|
59
80
|
```
|
|
60
81
|
|
|
61
82
|
---
|
|
62
83
|
|
|
63
|
-
##
|
|
84
|
+
## π§© Core API (examples β CommonJS)
|
|
64
85
|
|
|
65
|
-
Kaelum exposes
|
|
86
|
+
> Kaelum exposes a factory β use `require('kaelum')` and call it to get an app instance:
|
|
66
87
|
|
|
67
88
|
```js
|
|
68
89
|
const kaelum = require('kaelum');
|
|
69
90
|
const app = kaelum();
|
|
70
91
|
```
|
|
71
92
|
|
|
72
|
-
###
|
|
93
|
+
### `app.setConfig(options)`
|
|
73
94
|
|
|
74
|
-
|
|
95
|
+
Enable/disable common features:
|
|
75
96
|
|
|
76
97
|
```js
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
98
|
+
app.setConfig({
|
|
99
|
+
cors: true, // apply CORS (requires cors package in dependencies)
|
|
100
|
+
helmet: true, // apply Helmet
|
|
101
|
+
static: "public", // serve static files from "public"
|
|
102
|
+
bodyParser: true, // default: enabled (JSON + urlencoded)
|
|
103
|
+
logs: false, // enable request logging via morgan (if installed)
|
|
104
|
+
port: 3000 // prefered port (used when calling app.start() without port)
|
|
80
105
|
});
|
|
81
106
|
```
|
|
82
107
|
|
|
83
|
-
|
|
108
|
+
* `setConfig` persists settings to the Kaelum config and will install/remove Kaelum-managed middlewares.
|
|
109
|
+
* Kaelum enables JSON/urlencoded parsing by default so beginners won't forget to parse request bodies.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### `app.start(port, callback)`
|
|
84
114
|
|
|
85
|
-
|
|
115
|
+
Starts the HTTP server. If `port` is omitted, Kaelum reads `port` from `setConfig` or falls back to `3000`.
|
|
86
116
|
|
|
87
117
|
```js
|
|
88
|
-
|
|
118
|
+
app.start(3000, () => console.log('Running'));
|
|
89
119
|
```
|
|
90
120
|
|
|
91
|
-
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### `app.addRoute(path, handlers)` and `app.apiRoute(resource, handlers)`
|
|
92
124
|
|
|
93
|
-
|
|
125
|
+
Register routes easily:
|
|
94
126
|
|
|
95
127
|
```js
|
|
96
|
-
app.
|
|
97
|
-
|
|
98
|
-
|
|
128
|
+
app.addRoute('/home', {
|
|
129
|
+
get: (req, res) => res.send('Welcome!'),
|
|
130
|
+
post: (req, res) => res.send('Posted!')
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// apiRoute builds RESTy resources with nested subpaths:
|
|
134
|
+
app.apiRoute('users', {
|
|
135
|
+
get: listUsers,
|
|
136
|
+
post: createUser,
|
|
137
|
+
'/:id': {
|
|
138
|
+
get: getUserById,
|
|
139
|
+
put: updateUser,
|
|
140
|
+
delete: deleteUser
|
|
141
|
+
}
|
|
99
142
|
});
|
|
100
143
|
```
|
|
101
144
|
|
|
102
|
-
|
|
145
|
+
`addRoute` also accepts a single handler function (assumed `GET`).
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### `app.setMiddleware(...)`
|
|
150
|
+
|
|
151
|
+
Flexible helper to register middleware(s):
|
|
152
|
+
|
|
153
|
+
```js
|
|
154
|
+
// single middleware
|
|
155
|
+
app.setMiddleware(require('helmet')());
|
|
156
|
+
|
|
157
|
+
// array of middlewares
|
|
158
|
+
app.setMiddleware([mw1, mw2]);
|
|
159
|
+
|
|
160
|
+
// mount middleware on a path
|
|
161
|
+
app.setMiddleware('/admin', authMiddleware);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
103
165
|
|
|
104
|
-
###
|
|
166
|
+
### `app.redirect(from, to, status)`
|
|
105
167
|
|
|
106
|
-
|
|
168
|
+
Register a redirect route:
|
|
107
169
|
|
|
108
170
|
```js
|
|
109
|
-
|
|
171
|
+
app.redirect('/old-url', '/new-url', 302);
|
|
110
172
|
```
|
|
111
173
|
|
|
112
174
|
---
|
|
113
175
|
|
|
114
|
-
|
|
176
|
+
### `app.healthCheck(path = '/health')`
|
|
115
177
|
|
|
116
|
-
|
|
178
|
+
Adds a health endpoint returning `{ status: 'OK', uptime, timestamp, pid }`.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### `app.useErrorHandler(options)`
|
|
183
|
+
|
|
184
|
+
Attach Kaelum's default JSON error handler:
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
app.useErrorHandler({ exposeStack: false });
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
It will return standardized JSON for errors and log server-side errors (5xx) to `console.error`.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## π§ Local development & contributing
|
|
195
|
+
|
|
196
|
+
To develop Kaelum locally and test the CLI:
|
|
117
197
|
|
|
118
198
|
```bash
|
|
119
|
-
|
|
199
|
+
# clone
|
|
200
|
+
git clone https://github.com/<your-repo>/kaelum.git
|
|
120
201
|
cd kaelum
|
|
202
|
+
|
|
203
|
+
# install & link locally
|
|
204
|
+
npm install
|
|
121
205
|
npm link
|
|
206
|
+
|
|
207
|
+
# from any folder you can now run the CLI
|
|
208
|
+
npx kaelum create my-test --template web
|
|
209
|
+
# or
|
|
210
|
+
kaelum create my-test # if linked globally
|
|
122
211
|
```
|
|
123
212
|
|
|
124
|
-
|
|
213
|
+
---
|
|
125
214
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
215
|
+
|
|
216
|
+
## π Why Kaelum?
|
|
217
|
+
|
|
218
|
+
* Reduces repetitive boilerplate required to start Node/Express web projects.
|
|
219
|
+
* Opinionated scaffolding (MVC) helps beginners adopt better structure.
|
|
220
|
+
* Keeps a small API surface: easy to teach and document.
|
|
221
|
+
* Extensible β `setConfig` and middleware helpers allow adding features without exposing Express internals.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## β
Current status
|
|
226
|
+
|
|
227
|
+
> Kaelum is under active development. The CLI scaffolds web and API templates and the framework already includes the MVP helpers (`start`, `addRoute`, `apiRoute`, `setConfig`, `static`, `redirect`, `healthCheck`, `useErrorHandler`) and security toggles for `cors` and `helmet`.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## π Links
|
|
232
|
+
|
|
233
|
+
* GitHub: `https://github.com/MatheusCampagnolo/kaelum`
|
|
234
|
+
* npm: `https://www.npmjs.com/package/kaelum`
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## π§Ύ License
|
|
239
|
+
|
|
240
|
+
MIT β see [LICENSE](LICENSE).
|
|
129
241
|
|
|
130
242
|
---
|
|
131
243
|
|
|
132
|
-
##
|
|
244
|
+
## βοΈ Notes for maintainers
|
|
133
245
|
|
|
134
|
-
|
|
246
|
+
* Templates include `package.json` configured as `commonjs` for now (uses `require`/`module.exports`).
|
|
247
|
+
* Update template `package.json` dependencies to reference Kaelum version when releasing new npm versions.
|
|
248
|
+
* We plan to add full JSDoc for the public API, unit tests (Jest + Supertest) and a docs site in future iterations.
|
package/cli/create.js
CHANGED
|
@@ -6,47 +6,80 @@ const { copyTemplate } = require("./utils");
|
|
|
6
6
|
|
|
7
7
|
const templatesDir = path.resolve(__dirname, "templates");
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* createProject - create project from template
|
|
11
|
+
* @param {Object} defaults - optional { projectName, template }
|
|
12
|
+
*/
|
|
13
|
+
async function createProject(defaults = {}) {
|
|
10
14
|
console.log("π Bem-vindo ao Kaelum CLI!");
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
{
|
|
20
|
-
type: "list",
|
|
21
|
-
name: "template",
|
|
22
|
-
message: "Qual template vocΓͺ deseja usar?",
|
|
23
|
-
choices: ["web", "api"],
|
|
24
|
-
},
|
|
25
|
-
]);
|
|
26
|
-
|
|
27
|
-
const { projectName, template } = answers;
|
|
28
|
-
const targetDir = path.resolve(process.cwd(), projectName);
|
|
29
|
-
const templateDir = path.join(templatesDir, template);
|
|
30
|
-
|
|
31
|
-
if (template === "api") {
|
|
32
|
-
console.log(
|
|
33
|
-
'\nπ¦ O template API ainda estΓ‘ em desenvolvimento. Por favor, escolha o template "web".'
|
|
34
|
-
);
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
16
|
+
try {
|
|
17
|
+
// ensure templates dir exists
|
|
18
|
+
const templatesExists = await fs.pathExists(templatesDir);
|
|
19
|
+
if (!templatesExists) {
|
|
20
|
+
console.error("β DiretΓ³rio de templates nΓ£o encontrado no CLI.");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
37
23
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
24
|
+
// gather answers (use defaults when present)
|
|
25
|
+
const answers = await inq.prompt([
|
|
26
|
+
{
|
|
27
|
+
type: "input",
|
|
28
|
+
name: "projectName",
|
|
29
|
+
message: "Qual serΓ‘ o nome do seu projeto?",
|
|
30
|
+
default: defaults.projectName || "",
|
|
31
|
+
validate: (input) => (input ? true : "O nome nΓ£o pode ser vazio."),
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
type: "list",
|
|
35
|
+
name: "template",
|
|
36
|
+
message: "Qual template vocΓͺ deseja usar?",
|
|
37
|
+
choices: async () => {
|
|
38
|
+
// list available template folders
|
|
39
|
+
try {
|
|
40
|
+
const items = await fs.readdir(templatesDir, {
|
|
41
|
+
withFileTypes: true,
|
|
42
|
+
});
|
|
43
|
+
return items.filter((i) => i.isDirectory()).map((i) => i.name);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
return ["web", "api"];
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
default: defaults.template || "web",
|
|
49
|
+
},
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
const { projectName, template } = answers;
|
|
53
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
54
|
+
const templateDir = path.join(templatesDir, template);
|
|
44
55
|
|
|
45
|
-
|
|
56
|
+
// template existence check
|
|
57
|
+
const templateExists = await fs.pathExists(templateDir);
|
|
58
|
+
if (!templateExists) {
|
|
59
|
+
console.error(`\nβ Template "${template}" nΓ£o encontrado.`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
46
62
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
63
|
+
if (await fs.pathExists(targetDir)) {
|
|
64
|
+
console.error(
|
|
65
|
+
`\nβ A pasta "${projectName}" jΓ‘ existe. Escolha outro nome ou apague a pasta existente.`
|
|
66
|
+
);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// copy + update package.json
|
|
71
|
+
const result = await copyTemplate(templateDir, targetDir, projectName);
|
|
72
|
+
if (!result.ok) {
|
|
73
|
+
console.error(`\nβ Erro ao copiar o template: ${result.error}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(`\nβ
Projeto "${projectName}" criado com sucesso!`);
|
|
78
|
+
console.log(`β‘οΈ Acesse a pasta: cd ${projectName}`);
|
|
79
|
+
console.log(`β‘οΈ Inicie o projeto com: npm install && npm start\n`);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
console.error("β Erro inesperado:", err.message || err);
|
|
82
|
+
}
|
|
50
83
|
}
|
|
51
84
|
|
|
52
|
-
module.exports = { createProject };
|
|
85
|
+
module.exports = { createProject };
|
package/cli/index.js
CHANGED
|
@@ -1,11 +1,53 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { createProject } = require(
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { createProject } = require("./create");
|
|
3
|
+
const argv = process.argv.slice(2);
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
function printHelp() {
|
|
6
|
+
console.log(`Kaelum CLI
|
|
7
|
+
Usage:
|
|
8
|
+
kaelum create # interactive
|
|
9
|
+
kaelum create <name> # create using interactive template choice
|
|
10
|
+
kaelum create <name> --template web|api # non-interactive (name provided, template preselected)
|
|
11
|
+
kaelum help
|
|
12
|
+
`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function main() {
|
|
16
|
+
const [command, maybeName, maybeFlag, maybeTemplate] = argv;
|
|
17
|
+
|
|
18
|
+
if (
|
|
19
|
+
!command ||
|
|
20
|
+
command === "help" ||
|
|
21
|
+
command === "--help" ||
|
|
22
|
+
command === "-h"
|
|
23
|
+
) {
|
|
24
|
+
printHelp();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (command === "create") {
|
|
29
|
+
// non-interactive shorthand: kaelum create my-app --template web
|
|
30
|
+
if (maybeName && maybeFlag === "--template" && maybeTemplate) {
|
|
31
|
+
await createProject({ projectName: maybeName, template: maybeTemplate });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// non-interactive shorthand: kaelum create my-app (will still ask template)
|
|
36
|
+
if (maybeName && !maybeFlag) {
|
|
37
|
+
await createProject({ projectName: maybeName });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// otherwise interactive flow
|
|
42
|
+
await createProject();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
5
45
|
|
|
6
|
-
if (command === 'create') {
|
|
7
|
-
createProject();
|
|
8
|
-
} else {
|
|
9
46
|
console.log(`Comando nΓ£o reconhecido: ${command}`);
|
|
10
|
-
|
|
47
|
+
printHelp();
|
|
11
48
|
}
|
|
49
|
+
|
|
50
|
+
main().catch((err) => {
|
|
51
|
+
console.error("Error running Kaelum CLI:", err);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// app.js - example API project generated by Kaelum (API template)
|
|
2
|
+
const kaelum = require("kaelum");
|
|
3
|
+
|
|
4
|
+
const app = kaelum();
|
|
5
|
+
|
|
6
|
+
// enable basic safety + logs via setConfig
|
|
7
|
+
app.setConfig({
|
|
8
|
+
cors: true,
|
|
9
|
+
helmet: true,
|
|
10
|
+
logs: true, // uses morgan internally
|
|
11
|
+
bodyParser: true,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// mount routes
|
|
15
|
+
const routes = require("./routes");
|
|
16
|
+
routes(app);
|
|
17
|
+
|
|
18
|
+
// health check
|
|
19
|
+
app.healthCheck("/health");
|
|
20
|
+
|
|
21
|
+
// use Kaelum generic error handler (JSON responses)
|
|
22
|
+
app.useErrorHandler({ exposeStack: false });
|
|
23
|
+
|
|
24
|
+
// start server
|
|
25
|
+
const PORT = process.env.PORT || 4000;
|
|
26
|
+
app.start(PORT);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// controllers/usersController.js
|
|
2
|
+
// Simple in-memory users controller for demonstration.
|
|
3
|
+
|
|
4
|
+
let _id = 1;
|
|
5
|
+
const users = [
|
|
6
|
+
{ id: _id++, name: "Alice", email: "alice@example.com" },
|
|
7
|
+
{ id: _id++, name: "Bob", email: "bob@example.com" },
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
function getUsers(req, res) {
|
|
11
|
+
res.json({ data: users });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function createUser(req, res) {
|
|
15
|
+
const body = req.body || {};
|
|
16
|
+
if (!body.name || !body.email) {
|
|
17
|
+
return res
|
|
18
|
+
.status(400)
|
|
19
|
+
.json({ error: { message: "name and email required" } });
|
|
20
|
+
}
|
|
21
|
+
const user = { id: _id++, name: body.name, email: body.email };
|
|
22
|
+
users.push(user);
|
|
23
|
+
res.status(201).json({ data: user });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getUserById(req, res) {
|
|
27
|
+
const id = Number(req.params.id);
|
|
28
|
+
const u = users.find((x) => x.id === id);
|
|
29
|
+
if (!u) return res.status(404).json({ error: { message: "User not found" } });
|
|
30
|
+
res.json({ data: u });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function updateUser(req, res) {
|
|
34
|
+
const id = Number(req.params.id);
|
|
35
|
+
const u = users.find((x) => x.id === id);
|
|
36
|
+
if (!u) return res.status(404).json({ error: { message: "User not found" } });
|
|
37
|
+
const body = req.body || {};
|
|
38
|
+
if (body.name) u.name = body.name;
|
|
39
|
+
if (body.email) u.email = body.email;
|
|
40
|
+
res.json({ data: u });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function deleteUser(req, res) {
|
|
44
|
+
const id = Number(req.params.id);
|
|
45
|
+
const idx = users.findIndex((x) => x.id === id);
|
|
46
|
+
if (idx === -1)
|
|
47
|
+
return res.status(404).json({ error: { message: "User not found" } });
|
|
48
|
+
const removed = users.splice(idx, 1)[0];
|
|
49
|
+
res.json({ data: removed });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
getUsers,
|
|
54
|
+
createUser,
|
|
55
|
+
getUserById,
|
|
56
|
+
updateUser,
|
|
57
|
+
deleteUser,
|
|
58
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// middlewares/authMock.js
|
|
2
|
+
// Simple mock "authentication" middleware for demo purposes.
|
|
3
|
+
// Checks for header "x-api-key: secret" β if absent, returns 401.
|
|
4
|
+
|
|
5
|
+
module.exports = function (req, res, next) {
|
|
6
|
+
const key = req.headers["x-api-key"] || req.query.api_key;
|
|
7
|
+
if (!key || key !== "secret") {
|
|
8
|
+
return res
|
|
9
|
+
.status(401)
|
|
10
|
+
.json({ error: { message: "Unauthorized. Provide x-api-key: secret" } });
|
|
11
|
+
}
|
|
12
|
+
next();
|
|
13
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kaelum-api-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Exemplo de app API gerado pela CLI Kaelum",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"start": "node app.js",
|
|
7
|
+
"dev": "nodemon app.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"kaelum",
|
|
11
|
+
"api"
|
|
12
|
+
],
|
|
13
|
+
"author": "",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"kaelum": "^1.3.0",
|
|
17
|
+
"cors": "^2.8.5",
|
|
18
|
+
"helmet": "^6.0.0",
|
|
19
|
+
"morgan": "^1.10.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"nodemon": "^2.0.22"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// routes.js - registers API endpoints using app.apiRoute
|
|
2
|
+
const {
|
|
3
|
+
getUsers,
|
|
4
|
+
createUser,
|
|
5
|
+
getUserById,
|
|
6
|
+
updateUser,
|
|
7
|
+
deleteUser,
|
|
8
|
+
} = require("./controllers/usersController");
|
|
9
|
+
|
|
10
|
+
const auth = require("./middlewares/authMock");
|
|
11
|
+
|
|
12
|
+
module.exports = function (app) {
|
|
13
|
+
// Global example: apply auth middleware on /users POST (create)
|
|
14
|
+
// also demonstrate per-path middleware usage via setMiddleware(path, middleware)
|
|
15
|
+
app.setMiddleware("/users", (req, res, next) => {
|
|
16
|
+
// a small wrapper to demonstrate both setMiddleware signature and route-level control
|
|
17
|
+
// allow GET without auth, require auth for POST/PUT/DELETE by checking method
|
|
18
|
+
if (["POST", "PUT", "DELETE"].includes(req.method)) {
|
|
19
|
+
return require("./middlewares/authMock")(req, res, next);
|
|
20
|
+
}
|
|
21
|
+
next();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Resource routes using apiRoute
|
|
25
|
+
app.apiRoute("users", {
|
|
26
|
+
get: getUsers,
|
|
27
|
+
post: createUser,
|
|
28
|
+
"/:id": {
|
|
29
|
+
get: getUserById,
|
|
30
|
+
put: updateUser,
|
|
31
|
+
delete: deleteUser,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
};
|
package/cli/templates/web/app.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
|
+
// app.js - example project generated by Kaelum (Web template)
|
|
1
2
|
const kaelum = require("kaelum");
|
|
3
|
+
|
|
2
4
|
const app = kaelum();
|
|
3
5
|
|
|
4
|
-
//
|
|
6
|
+
// Enable basic security + static serving via setConfig (uses Kaelum internals)
|
|
5
7
|
app.setConfig({
|
|
6
8
|
cors: true,
|
|
7
9
|
helmet: true,
|
|
10
|
+
static: "public", // will serve ./public
|
|
11
|
+
bodyParser: true, // default enabled β explicit for clarity
|
|
8
12
|
});
|
|
9
13
|
|
|
10
|
-
//
|
|
14
|
+
// Register routes (routes.js uses Kaelum helpers)
|
|
11
15
|
const routes = require("./routes");
|
|
12
16
|
routes(app);
|
|
13
17
|
|
|
14
|
-
//
|
|
15
|
-
app.
|
|
18
|
+
// optional: health check endpoint
|
|
19
|
+
app.healthCheck("/health");
|
|
20
|
+
|
|
21
|
+
// install Kaelum default error handler (returns JSON on errors)
|
|
22
|
+
app.useErrorHandler({ exposeStack: false });
|
|
23
|
+
|
|
24
|
+
// Start server (explicit port for template demo)
|
|
25
|
+
const PORT = process.env.PORT || 3000;
|
|
26
|
+
app.start(PORT);
|