kaelum 1.2.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 +158 -61
- package/cli/create.js +71 -31
- package/cli/index.js +49 -7
- package/cli/templates/api/app.js +16 -2
- package/cli/templates/api/controllers/usersController.js +58 -0
- package/cli/templates/api/middlewares/authMock.js +13 -0
- package/cli/templates/api/package.json +14 -7
- package/cli/templates/api/routes.js +31 -8
- 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/controllers/userController.js +0 -13
- package/cli/templates/api/middlewares/logger.js +0 -6
- package/utils/.gitkeep +0 -0
package/README.md
CHANGED
|
@@ -1,151 +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
|
|
59
67
|
```
|
|
60
68
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
## ๐ API Template Structure
|
|
64
|
-
|
|
65
|
-
After running `npx kaelum create` using the API template, the structure looks like this:
|
|
69
|
+
### API template (`--template api`)
|
|
66
70
|
|
|
67
71
|
```
|
|
68
72
|
my-api-app/
|
|
69
73
|
โโโ controllers/
|
|
70
|
-
โ โโโ
|
|
74
|
+
โ โโโ usersController.js
|
|
71
75
|
โโโ middlewares/
|
|
72
|
-
โ โโโ
|
|
76
|
+
โ โโโ authMock.js
|
|
73
77
|
โโโ routes.js
|
|
74
78
|
โโโ app.js
|
|
75
|
-
|
|
79
|
+
โโโ package.json
|
|
76
80
|
```
|
|
77
81
|
|
|
78
82
|
---
|
|
79
83
|
|
|
80
|
-
##
|
|
84
|
+
## ๐งฉ Core API (examples โ CommonJS)
|
|
81
85
|
|
|
82
|
-
Kaelum exposes
|
|
86
|
+
> Kaelum exposes a factory โ use `require('kaelum')` and call it to get an app instance:
|
|
83
87
|
|
|
84
88
|
```js
|
|
85
89
|
const kaelum = require('kaelum');
|
|
86
90
|
const app = kaelum();
|
|
87
91
|
```
|
|
88
92
|
|
|
89
|
-
###
|
|
93
|
+
### `app.setConfig(options)`
|
|
90
94
|
|
|
91
|
-
|
|
95
|
+
Enable/disable common features:
|
|
92
96
|
|
|
93
97
|
```js
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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)
|
|
97
105
|
});
|
|
98
106
|
```
|
|
99
107
|
|
|
100
|
-
|
|
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.
|
|
101
110
|
|
|
102
|
-
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### `app.start(port, callback)`
|
|
114
|
+
|
|
115
|
+
Starts the HTTP server. If `port` is omitted, Kaelum reads `port` from `setConfig` or falls back to `3000`.
|
|
103
116
|
|
|
104
117
|
```js
|
|
105
|
-
|
|
118
|
+
app.start(3000, () => console.log('Running'));
|
|
106
119
|
```
|
|
107
120
|
|
|
108
|
-
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### `app.addRoute(path, handlers)` and `app.apiRoute(resource, handlers)`
|
|
109
124
|
|
|
110
|
-
|
|
125
|
+
Register routes easily:
|
|
111
126
|
|
|
112
127
|
```js
|
|
113
|
-
app.
|
|
114
|
-
|
|
115
|
-
|
|
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
|
+
}
|
|
116
142
|
});
|
|
117
143
|
```
|
|
118
144
|
|
|
119
|
-
|
|
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
|
+
---
|
|
165
|
+
|
|
166
|
+
### `app.redirect(from, to, status)`
|
|
167
|
+
|
|
168
|
+
Register a redirect route:
|
|
169
|
+
|
|
170
|
+
```js
|
|
171
|
+
app.redirect('/old-url', '/new-url', 302);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### `app.healthCheck(path = '/health')`
|
|
177
|
+
|
|
178
|
+
Adds a health endpoint returning `{ status: 'OK', uptime, timestamp, pid }`.
|
|
120
179
|
|
|
121
|
-
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### `app.useErrorHandler(options)`
|
|
122
183
|
|
|
123
|
-
|
|
184
|
+
Attach Kaelum's default JSON error handler:
|
|
124
185
|
|
|
125
186
|
```js
|
|
126
|
-
|
|
187
|
+
app.useErrorHandler({ exposeStack: false });
|
|
127
188
|
```
|
|
128
189
|
|
|
190
|
+
It will return standardized JSON for errors and log server-side errors (5xx) to `console.error`.
|
|
191
|
+
|
|
129
192
|
---
|
|
130
193
|
|
|
131
|
-
##
|
|
194
|
+
## ๐ง Local development & contributing
|
|
132
195
|
|
|
133
|
-
|
|
196
|
+
To develop Kaelum locally and test the CLI:
|
|
134
197
|
|
|
135
198
|
```bash
|
|
136
|
-
|
|
199
|
+
# clone
|
|
200
|
+
git clone https://github.com/<your-repo>/kaelum.git
|
|
137
201
|
cd kaelum
|
|
202
|
+
|
|
203
|
+
# install & link locally
|
|
204
|
+
npm install
|
|
138
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
|
|
139
211
|
```
|
|
140
212
|
|
|
141
|
-
|
|
213
|
+
---
|
|
142
214
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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).
|
|
146
241
|
|
|
147
242
|
---
|
|
148
243
|
|
|
149
|
-
##
|
|
244
|
+
## โ๏ธ Notes for maintainers
|
|
150
245
|
|
|
151
|
-
|
|
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,40 +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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
+
}
|
|
23
|
+
|
|
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);
|
|
37
55
|
|
|
38
|
-
|
|
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
|
+
}
|
|
39
62
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
+
}
|
|
43
83
|
}
|
|
44
84
|
|
|
45
|
-
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
|
+
});
|
package/cli/templates/api/app.js
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
|
+
// app.js - example API project generated by Kaelum (API template)
|
|
1
2
|
const kaelum = require("kaelum");
|
|
3
|
+
|
|
2
4
|
const app = kaelum();
|
|
3
5
|
|
|
6
|
+
// enable basic safety + logs via setConfig
|
|
4
7
|
app.setConfig({
|
|
5
8
|
cors: true,
|
|
6
|
-
helmet: true
|
|
9
|
+
helmet: true,
|
|
10
|
+
logs: true, // uses morgan internally
|
|
11
|
+
bodyParser: true,
|
|
7
12
|
});
|
|
8
13
|
|
|
14
|
+
// mount routes
|
|
9
15
|
const routes = require("./routes");
|
|
10
16
|
routes(app);
|
|
11
17
|
|
|
12
|
-
|
|
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
|
+
};
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kaelum-api-app",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "
|
|
5
|
-
"main": "app.js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Exemplo de app API gerado pela CLI Kaelum",
|
|
6
5
|
"scripts": {
|
|
7
6
|
"start": "node app.js",
|
|
8
7
|
"dev": "nodemon app.js"
|
|
9
8
|
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"kaelum",
|
|
11
|
+
"api"
|
|
12
|
+
],
|
|
13
|
+
"author": "",
|
|
14
|
+
"license": "MIT",
|
|
10
15
|
"dependencies": {
|
|
11
|
-
"kaelum": "1.
|
|
16
|
+
"kaelum": "^1.3.0",
|
|
17
|
+
"cors": "^2.8.5",
|
|
18
|
+
"helmet": "^6.0.0",
|
|
19
|
+
"morgan": "^1.10.0"
|
|
12
20
|
},
|
|
13
21
|
"devDependencies": {
|
|
14
22
|
"nodemon": "^2.0.22"
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,11 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
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");
|
|
3
9
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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();
|
|
8
22
|
});
|
|
9
|
-
}
|
|
10
23
|
|
|
11
|
-
|
|
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
|
+
};
|