@gieo/express 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/dist/index.js CHANGED
@@ -1,52 +1,9 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
- var __asyncValues = (this && this.__asyncValues) || function (o) {
39
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
40
- var m = o[Symbol.asyncIterator], i;
41
- return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
42
- function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
43
- function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
44
- };
45
2
  Object.defineProperty(exports, "__esModule", { value: true });
46
- var http_1 = require("http");
47
- var url_1 = require("url");
48
- var ExpressPlus = /** @class */ (function () {
49
- function ExpressPlus() {
3
+ const http_1 = require("http");
4
+ const url_1 = require("url");
5
+ class ExpressPlus {
6
+ constructor() {
50
7
  this.routes = {
51
8
  GET: [],
52
9
  POST: [],
@@ -56,92 +13,53 @@ var ExpressPlus = /** @class */ (function () {
56
13
  };
57
14
  this.middlewares = [];
58
15
  }
59
- ExpressPlus.prototype.addRoute = function (method, path, handler) {
60
- this.routes[method].push({ path: path, handler: handler });
61
- };
62
- ExpressPlus.prototype.use = function (middleware) {
16
+ addRoute(method, path, handler) {
17
+ this.routes[method].push({ path, handler });
18
+ }
19
+ use(middleware) {
63
20
  this.middlewares.push(middleware);
64
- };
65
- ExpressPlus.prototype.get = function (path, handler) {
21
+ }
22
+ get(path, handler) {
66
23
  this.addRoute("GET", path, handler);
67
- };
68
- ExpressPlus.prototype.post = function (path, handler) {
24
+ }
25
+ post(path, handler) {
69
26
  this.addRoute("POST", path, handler);
70
- };
71
- ExpressPlus.prototype.put = function (path, handler) {
27
+ }
28
+ put(path, handler) {
72
29
  this.addRoute("PUT", path, handler);
73
- };
74
- ExpressPlus.prototype.patch = function (path, handler) {
30
+ }
31
+ patch(path, handler) {
75
32
  this.addRoute("PATCH", path, handler);
76
- };
77
- ExpressPlus.prototype.delete = function (path, handler) {
33
+ }
34
+ delete(path, handler) {
78
35
  this.addRoute("DELETE", path, handler);
79
- };
80
- ExpressPlus.prototype.listen = function (port, callback) {
81
- var _this = this;
82
- var server = (0, http_1.createServer)(function (req, res) {
83
- var method = req.method;
84
- var parsedUrl = (0, url_1.parse)(req.url || "", true);
85
- var pathname = parsedUrl.pathname || "/";
86
- var route = _this.routes[method].find(function (r) { return r.path === pathname; });
87
- var extendedReq = req;
88
- var extendedRes = res;
36
+ }
37
+ listen(port, callback) {
38
+ const server = (0, http_1.createServer)((req, res) => {
39
+ const method = req.method;
40
+ const parsedUrl = (0, url_1.parse)(req.url || "", true);
41
+ const pathname = parsedUrl.pathname || "/";
42
+ const extendedReq = req;
43
+ const extendedRes = res;
89
44
  extendedReq.query = parsedUrl.query;
90
- extendedReq.getBody = function () { return __awaiter(_this, void 0, void 0, function () {
91
- var chunks, _a, extendedReq_1, extendedReq_1_1, chunk, e_1_1, raw;
92
- var _b, e_1, _c, _d;
93
- return __generator(this, function (_e) {
94
- switch (_e.label) {
95
- case 0:
96
- if (extendedReq.body)
97
- return [2 /*return*/, extendedReq.body];
98
- chunks = [];
99
- _e.label = 1;
100
- case 1:
101
- _e.trys.push([1, 6, 7, 12]);
102
- _a = true, extendedReq_1 = __asyncValues(extendedReq);
103
- _e.label = 2;
104
- case 2: return [4 /*yield*/, extendedReq_1.next()];
105
- case 3:
106
- if (!(extendedReq_1_1 = _e.sent(), _b = extendedReq_1_1.done, !_b)) return [3 /*break*/, 5];
107
- _d = extendedReq_1_1.value;
108
- _a = false;
109
- chunk = _d;
110
- chunks.push(chunk);
111
- _e.label = 4;
112
- case 4:
113
- _a = true;
114
- return [3 /*break*/, 2];
115
- case 5: return [3 /*break*/, 12];
116
- case 6:
117
- e_1_1 = _e.sent();
118
- e_1 = { error: e_1_1 };
119
- return [3 /*break*/, 12];
120
- case 7:
121
- _e.trys.push([7, , 10, 11]);
122
- if (!(!_a && !_b && (_c = extendedReq_1.return))) return [3 /*break*/, 9];
123
- return [4 /*yield*/, _c.call(extendedReq_1)];
124
- case 8:
125
- _e.sent();
126
- _e.label = 9;
127
- case 9: return [3 /*break*/, 11];
128
- case 10:
129
- if (e_1) throw e_1.error;
130
- return [7 /*endfinally*/];
131
- case 11: return [7 /*endfinally*/];
132
- case 12:
133
- raw = Buffer.concat(chunks).toString();
134
- extendedReq.bodyRaw = raw;
135
- try {
136
- extendedReq.body = JSON.parse(raw);
137
- }
138
- catch (_f) {
139
- extendedReq.body = {};
140
- }
141
- return [2 /*return*/, extendedReq.body];
142
- }
143
- });
144
- }); };
45
+ extendedReq.params = {};
46
+ extendedReq.getBody = async () => {
47
+ if (extendedReq.body)
48
+ return extendedReq.body;
49
+ const chunks = [];
50
+ for await (const chunk of extendedReq) {
51
+ chunks.push(chunk);
52
+ }
53
+ const raw = Buffer.concat(chunks).toString();
54
+ extendedReq.bodyRaw = raw;
55
+ try {
56
+ extendedReq.body = JSON.parse(raw);
57
+ }
58
+ catch {
59
+ extendedReq.body = {};
60
+ }
61
+ return extendedReq.body;
62
+ };
145
63
  extendedRes.status = function (code) {
146
64
  extendedRes.statusCode = code;
147
65
  return extendedRes;
@@ -150,9 +68,33 @@ var ExpressPlus = /** @class */ (function () {
150
68
  extendedRes.setHeader("Content-Type", "application/json");
151
69
  extendedRes.end(JSON.stringify(data));
152
70
  };
153
- var i = 0;
154
- var next = function () {
155
- var middleware = _this.middlewares[i++];
71
+ // 🔍 Tìm route phù hợp (hỗ trợ dynamic route)
72
+ const route = this.routes[method].find((r) => {
73
+ const routeParts = r.path.split("/").filter(Boolean);
74
+ const urlParts = pathname.split("/").filter(Boolean);
75
+ if (routeParts.length !== urlParts.length)
76
+ return false;
77
+ return routeParts.every((part, i) => {
78
+ return part.startsWith(":") || part === urlParts[i];
79
+ });
80
+ });
81
+ // 🧠 Trích xuất params nếu có
82
+ if (route) {
83
+ const routeParts = route.path.split("/").filter(Boolean);
84
+ const urlParts = pathname.split("/").filter(Boolean);
85
+ routeParts.forEach((part, i) => {
86
+ if (part.startsWith(":")) {
87
+ const key = part.slice(1);
88
+ extendedReq.params[key] = urlParts[i];
89
+ }
90
+ });
91
+ }
92
+ // 🧪 Logging đơn giản
93
+ console.log(`[${method}] ${pathname}`);
94
+ // 🧩 Middleware + Route handler
95
+ let i = 0;
96
+ const next = () => {
97
+ const middleware = this.middlewares[i++];
156
98
  if (middleware) {
157
99
  middleware(extendedReq, extendedRes, next);
158
100
  }
@@ -160,15 +102,12 @@ var ExpressPlus = /** @class */ (function () {
160
102
  route.handler(extendedReq, extendedRes);
161
103
  }
162
104
  else {
163
- extendedRes.status(404).end("Not Found");
105
+ extendedRes.status(404).json({ message: "Not Found" });
164
106
  }
165
107
  };
166
108
  next();
167
109
  });
168
110
  server.listen(port, callback);
169
- };
170
- return ExpressPlus;
171
- }());
172
- // ✅ Export cho cả ES Module và CommonJS
111
+ }
112
+ }
173
113
  exports.default = ExpressPlus;
174
- module.exports = ExpressPlus;
package/dist/test.js CHANGED
@@ -1,182 +1,106 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
- var __rest = (this && this.__rest) || function (s, e) {
39
- var t = {};
40
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
41
- t[p] = s[p];
42
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
43
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
44
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
45
- t[p[i]] = s[p[i]];
46
- }
47
- return t;
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
48
4
  };
49
5
  Object.defineProperty(exports, "__esModule", { value: true });
50
- var index_1 = require("./index");
51
- var utils_1 = require("@gieo/utils");
52
- var app = new index_1.default();
53
- app.post("/calc", function (req, res) { return __awaiter(void 0, void 0, void 0, function () {
54
- var _a, op, numbers, values, result;
55
- return __generator(this, function (_b) {
56
- switch (_b.label) {
57
- case 0: return [4 /*yield*/, req.getBody()];
58
- case 1:
59
- _a = _b.sent(), op = _a.op, numbers = __rest(_a, ["op"]);
60
- values = Object.values(numbers)
61
- .map(Number)
62
- .filter(function (v) { return !isNaN(v); });
63
- if (values.length < 2) {
64
- return [2 /*return*/, res.status(400).json({
65
- statusCode: 400,
66
- success: false,
67
- message: "Need at least two numeric values",
68
- })];
69
- }
70
- try {
71
- switch (op) {
72
- case "sum":
73
- result = utils_1.sum.apply(void 0, values);
74
- break;
75
- case "sub":
76
- result = utils_1.sub.apply(void 0, values);
77
- break;
78
- case "mul":
79
- result = utils_1.mul.apply(void 0, values);
80
- break;
81
- case "div":
82
- result = utils_1.div.apply(void 0, values);
83
- break;
84
- default:
85
- return [2 /*return*/, res.status(400).json({
86
- statusCode: 400,
87
- success: false,
88
- message: "Invalid operator",
89
- })];
90
- }
91
- return [2 /*return*/, res.status(200).json({
92
- statusCode: 200,
93
- success: true,
94
- result: result,
95
- })];
96
- }
97
- catch (err) {
98
- return [2 /*return*/, res.status(500).json({
99
- statusCode: 500,
100
- success: false,
101
- message: err.message,
102
- })];
103
- }
104
- return [2 /*return*/];
6
+ const index_1 = __importDefault(require("./index"));
7
+ const utils_1 = require("@gieo/utils");
8
+ const app = new index_1.default();
9
+ app.post("/calc", async (req, res) => {
10
+ const { op, ...numbers } = await req.getBody();
11
+ // Lấy tất cả giá trị số từ body
12
+ const values = Object.values(numbers)
13
+ .map(Number)
14
+ .filter((v) => !isNaN(v));
15
+ if (values.length < 2) {
16
+ return res.status(400).json({
17
+ statusCode: 400,
18
+ success: false,
19
+ message: "Need at least two numeric values",
20
+ });
21
+ }
22
+ let result;
23
+ try {
24
+ switch (op) {
25
+ case "sum":
26
+ result = (0, utils_1.sum)(...values);
27
+ break;
28
+ case "sub":
29
+ result = (0, utils_1.sub)(...values);
30
+ break;
31
+ case "mul":
32
+ result = (0, utils_1.mul)(...values);
33
+ break;
34
+ case "div":
35
+ result = (0, utils_1.div)(...values);
36
+ break;
37
+ default:
38
+ return res.status(400).json({
39
+ statusCode: 400,
40
+ success: false,
41
+ message: "Invalid operator",
42
+ });
105
43
  }
106
- });
107
- }); });
108
- // Các route cơ bản
109
- app.get("/", function (req, res) {
110
- return res.status(200).json({ success: true, status: 200, result: "GET / OK" });
111
- });
112
- app.put("/", function (req, res) {
113
- return res.status(200).json({ success: true, status: 200, result: "PUT / OK" });
114
- });
115
- app.post("/", function (req, res) {
116
- return res.status(200).json({ success: true, status: 200, result: "POST / OK" });
117
- });
118
- app.patch("/", function (req, res) {
119
- return res.status(200).json({ success: true, status: 200, result: "PATCH / OK" });
120
- });
121
- app.delete("/", function (req, res) {
122
- return res.status(200).json({ success: true, status: 200, result: "DELETE / OK" });
44
+ return res.status(200).json({
45
+ statusCode: 200,
46
+ success: true,
47
+ result,
48
+ });
49
+ }
50
+ catch (err) {
51
+ return res.status(500).json({
52
+ statusCode: 500,
53
+ success: false,
54
+ message: err.message,
55
+ });
56
+ }
123
57
  });
124
- var mathRoute = function (op) { return function (req, res) { return __awaiter(void 0, void 0, void 0, function () {
125
- var _a, a, b, result;
126
- return __generator(this, function (_b) {
127
- switch (_b.label) {
128
- case 0: return [4 /*yield*/, req.getBody()];
129
- case 1:
130
- _a = _b.sent(), a = _a.a, b = _a.b;
131
- if (typeof a !== "number" || typeof b !== "number") {
132
- return [2 /*return*/, res.status(400).json({
133
- success: false,
134
- status: 400,
135
- result: "Invalid input. 'a' and 'b' must be numbers.",
136
- })];
137
- }
138
- try {
139
- result = op(a, b);
140
- res.status(200).json({ success: true, status: 200, result: result });
141
- }
142
- catch (err) {
143
- res
144
- .status(500)
145
- .json({ success: false, status: 500, result: err.message });
146
- }
147
- return [2 /*return*/];
148
- }
149
- });
150
- }); }; };
58
+ // Các route bản
59
+ app.get("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "GET / OK" }));
60
+ app.put("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "PUT / OK" }));
61
+ app.post("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "POST / OK" }));
62
+ app.patch("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "PATCH / OK" }));
63
+ app.delete("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "DELETE / OK" }));
64
+ const mathRoute = (op) => async (req, res) => {
65
+ const { a, b } = await req.getBody();
66
+ if (typeof a !== "number" || typeof b !== "number") {
67
+ return res.status(400).json({
68
+ success: false,
69
+ status: 400,
70
+ result: "Invalid input. 'a' and 'b' must be numbers.",
71
+ });
72
+ }
73
+ try {
74
+ const result = op(a, b);
75
+ res.status(200).json({ success: true, status: 200, result });
76
+ }
77
+ catch (err) {
78
+ res
79
+ .status(500)
80
+ .json({ success: false, status: 500, result: err.message });
81
+ }
82
+ };
151
83
  // Math operations
152
84
  app.post("/sum", mathRoute(utils_1.sum));
153
85
  app.post("/sub", mathRoute(utils_1.sub));
154
86
  app.post("/mul", mathRoute(utils_1.mul));
155
- app.post("/div", function (req, res) { return __awaiter(void 0, void 0, void 0, function () {
156
- var _a, a, b, result;
157
- return __generator(this, function (_b) {
158
- switch (_b.label) {
159
- case 0: return [4 /*yield*/, req.getBody()];
160
- case 1:
161
- _a = _b.sent(), a = _a.a, b = _a.b;
162
- if (typeof a !== "number" || typeof b !== "number") {
163
- return [2 /*return*/, res.status(400).json({
164
- success: false,
165
- status: 400,
166
- result: "Invalid input. 'a' and 'b' must be numbers.",
167
- })];
168
- }
169
- if (b === 0) {
170
- return [2 /*return*/, res
171
- .status(400)
172
- .json({ success: false, status: 400, result: "Cannot divide by zero" })];
173
- }
174
- result = (0, utils_1.div)(a, b);
175
- res.status(200).json({ success: true, status: 200, result: result });
176
- return [2 /*return*/];
177
- }
178
- });
179
- }); });
180
- app.listen(3000, function () {
87
+ app.post("/div", async (req, res) => {
88
+ const { a, b } = await req.getBody();
89
+ if (typeof a !== "number" || typeof b !== "number") {
90
+ return res.status(400).json({
91
+ success: false,
92
+ status: 400,
93
+ result: "Invalid input. 'a' and 'b' must be numbers.",
94
+ });
95
+ }
96
+ if (b === 0) {
97
+ return res
98
+ .status(400)
99
+ .json({ success: false, status: 400, result: "Cannot divide by zero" });
100
+ }
101
+ const result = (0, utils_1.div)(a, b);
102
+ res.status(200).json({ success: true, status: 200, result });
103
+ });
104
+ app.listen(3000, () => {
181
105
  console.log("✅ Server is running at http://localhost:3000");
182
106
  });
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@gieo/express",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "",
5
- "main": "./dist/test.js",
5
+ "main": "./dist/index.js",
6
6
  "keywords": [],
7
7
  "author": "",
8
8
  "license": "ISC",
9
9
  "devDependencies": {
10
10
  "@gieo/utils": "^1.0.5",
11
- "@types/node": "^24.2.0",
11
+ "@types/node": "^24.2.1",
12
12
  "jiti": "^2.5.1",
13
13
  "typescript": "^5.9.2"
14
14
  },
15
15
  "scripts": {
16
- "test": "echo \"Error: no test specified\" && exit 1"
16
+ "test": "node dist/test.js"
17
17
  }
18
18
  }
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ import { parse } from "url";
4
4
  // Mở rộng Request
5
5
  interface ExtendedRequest extends IncomingMessage {
6
6
  query?: Record<string, string | string[]>;
7
+ params?: Record<string, string>;
7
8
  bodyRaw?: string;
8
9
  body?: any;
9
10
  getBody: () => Promise<any>;
@@ -78,12 +79,11 @@ class ExpressPlus {
78
79
  const parsedUrl = parse(req.url || "", true);
79
80
  const pathname = parsedUrl.pathname || "/";
80
81
 
81
- const route = this.routes[method].find((r) => r.path === pathname);
82
-
83
82
  const extendedReq = req as ExtendedRequest;
84
83
  const extendedRes = res as ExtendedResponse;
85
84
 
86
85
  extendedReq.query = parsedUrl.query;
86
+ extendedReq.params = {};
87
87
  extendedReq.getBody = async () => {
88
88
  if (extendedReq.body) return extendedReq.body;
89
89
 
@@ -114,6 +114,35 @@ class ExpressPlus {
114
114
  extendedRes.end(JSON.stringify(data));
115
115
  };
116
116
 
117
+ // 🔍 Tìm route phù hợp (hỗ trợ dynamic route)
118
+ const route = this.routes[method].find((r) => {
119
+ const routeParts = r.path.split("/").filter(Boolean);
120
+ const urlParts = pathname.split("/").filter(Boolean);
121
+
122
+ if (routeParts.length !== urlParts.length) return false;
123
+
124
+ return routeParts.every((part, i) => {
125
+ return part.startsWith(":") || part === urlParts[i];
126
+ });
127
+ });
128
+
129
+ // 🧠 Trích xuất params nếu có
130
+ if (route) {
131
+ const routeParts = route.path.split("/").filter(Boolean);
132
+ const urlParts = pathname.split("/").filter(Boolean);
133
+
134
+ routeParts.forEach((part, i) => {
135
+ if (part.startsWith(":")) {
136
+ const key = part.slice(1);
137
+ extendedReq.params![key] = urlParts[i];
138
+ }
139
+ });
140
+ }
141
+
142
+ // 🧪 Logging đơn giản
143
+ console.log(`[${method}] ${pathname}`);
144
+
145
+ // 🧩 Middleware + Route handler
117
146
  let i = 0;
118
147
  const next = () => {
119
148
  const middleware = this.middlewares[i++];
@@ -122,7 +151,7 @@ class ExpressPlus {
122
151
  } else if (route) {
123
152
  route.handler(extendedReq, extendedRes);
124
153
  } else {
125
- extendedRes.status(404).end("Not Found");
154
+ extendedRes.status(404).json({ message: "Not Found" });
126
155
  }
127
156
  };
128
157
 
package/tsconfig.json CHANGED
@@ -4,5 +4,7 @@
4
4
  "target": "ES2020",
5
5
  "esModuleInterop": true,
6
6
  "allowSyntheticDefaultImports": true,
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
7
9
  }
8
10
  }
package/src/index.js DELETED
@@ -1,89 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const http_1 = require("http");
4
- const url_1 = require("url");
5
- class ExpressPlus {
6
- constructor() {
7
- this.routes = {
8
- GET: [],
9
- POST: [],
10
- PUT: [],
11
- PATCH: [],
12
- DELETE: [],
13
- };
14
- this.middlewares = [];
15
- }
16
- addRoute(method, path, handler) {
17
- this.routes[method].push({ path, handler });
18
- }
19
- use(middleware) {
20
- this.middlewares.push(middleware);
21
- }
22
- get(path, handler) {
23
- this.addRoute("GET", path, handler);
24
- }
25
- post(path, handler) {
26
- this.addRoute("POST", path, handler);
27
- }
28
- put(path, handler) {
29
- this.addRoute("PUT", path, handler);
30
- }
31
- patch(path, handler) {
32
- this.addRoute("PATCH", path, handler);
33
- }
34
- delete(path, handler) {
35
- this.addRoute("DELETE", path, handler);
36
- }
37
- listen(port, callback) {
38
- const server = (0, http_1.createServer)((req, res) => {
39
- const method = req.method;
40
- const parsedUrl = (0, url_1.parse)(req.url || "", true);
41
- const pathname = parsedUrl.pathname || "/";
42
- const route = this.routes[method].find((r) => r.path === pathname);
43
- const extendedReq = req;
44
- const extendedRes = res;
45
- extendedReq.query = parsedUrl.query;
46
- extendedReq.getBody = async () => {
47
- if (extendedReq.body)
48
- return extendedReq.body;
49
- const chunks = [];
50
- for await (const chunk of extendedReq) {
51
- chunks.push(chunk);
52
- }
53
- const raw = Buffer.concat(chunks).toString();
54
- extendedReq.bodyRaw = raw;
55
- try {
56
- extendedReq.body = JSON.parse(raw);
57
- }
58
- catch {
59
- extendedReq.body = {};
60
- }
61
- return extendedReq.body;
62
- };
63
- extendedRes.status = function (code) {
64
- extendedRes.statusCode = code;
65
- return extendedRes;
66
- };
67
- extendedRes.json = function (data) {
68
- extendedRes.setHeader("Content-Type", "application/json");
69
- extendedRes.end(JSON.stringify(data));
70
- };
71
- let i = 0;
72
- const next = () => {
73
- const middleware = this.middlewares[i++];
74
- if (middleware) {
75
- middleware(extendedReq, extendedRes, next);
76
- }
77
- else if (route) {
78
- route.handler(extendedReq, extendedRes);
79
- }
80
- else {
81
- extendedRes.status(404).end("Not Found");
82
- }
83
- };
84
- next();
85
- });
86
- server.listen(port, callback);
87
- }
88
- }
89
- exports.default = ExpressPlus;
package/src/test.js DELETED
@@ -1,106 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const index_1 = __importDefault(require("./index"));
7
- const utils_1 = require("@gieo/utils");
8
- const app = new index_1.default();
9
- app.post("/calc", async (req, res) => {
10
- const { op, ...numbers } = await req.getBody();
11
- // Lấy tất cả giá trị số từ body
12
- const values = Object.values(numbers)
13
- .map(Number)
14
- .filter((v) => !isNaN(v));
15
- if (values.length < 2) {
16
- return res.status(400).json({
17
- statusCode: 400,
18
- success: false,
19
- message: "Need at least two numeric values",
20
- });
21
- }
22
- let result;
23
- try {
24
- switch (op) {
25
- case "sum":
26
- result = (0, utils_1.sum)(...values);
27
- break;
28
- case "sub":
29
- result = (0, utils_1.sub)(...values);
30
- break;
31
- case "mul":
32
- result = (0, utils_1.mul)(...values);
33
- break;
34
- case "div":
35
- result = (0, utils_1.div)(...values);
36
- break;
37
- default:
38
- return res.status(400).json({
39
- statusCode: 400,
40
- success: false,
41
- message: "Invalid operator",
42
- });
43
- }
44
- return res.status(200).json({
45
- statusCode: 200,
46
- success: true,
47
- result,
48
- });
49
- }
50
- catch (err) {
51
- return res.status(500).json({
52
- statusCode: 500,
53
- success: false,
54
- message: err.message,
55
- });
56
- }
57
- });
58
- // Các route cơ bản
59
- app.get("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "GET / OK" }));
60
- app.put("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "PUT / OK" }));
61
- app.post("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "POST / OK" }));
62
- app.patch("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "PATCH / OK" }));
63
- app.delete("/", (req, res) => res.status(200).json({ success: true, status: 200, result: "DELETE / OK" }));
64
- const mathRoute = (op) => async (req, res) => {
65
- const { a, b } = await req.getBody();
66
- if (typeof a !== "number" || typeof b !== "number") {
67
- return res.status(400).json({
68
- success: false,
69
- status: 400,
70
- result: "Invalid input. 'a' and 'b' must be numbers.",
71
- });
72
- }
73
- try {
74
- const result = op(a, b);
75
- res.status(200).json({ success: true, status: 200, result });
76
- }
77
- catch (err) {
78
- res
79
- .status(500)
80
- .json({ success: false, status: 500, result: err.message });
81
- }
82
- };
83
- // Math operations
84
- app.post("/sum", mathRoute(utils_1.sum));
85
- app.post("/sub", mathRoute(utils_1.sub));
86
- app.post("/mul", mathRoute(utils_1.mul));
87
- app.post("/div", async (req, res) => {
88
- const { a, b } = await req.getBody();
89
- if (typeof a !== "number" || typeof b !== "number") {
90
- return res.status(400).json({
91
- success: false,
92
- status: 400,
93
- result: "Invalid input. 'a' and 'b' must be numbers.",
94
- });
95
- }
96
- if (b === 0) {
97
- return res
98
- .status(400)
99
- .json({ success: false, status: 400, result: "Cannot divide by zero" });
100
- }
101
- const result = (0, utils_1.div)(a, b);
102
- res.status(200).json({ success: true, status: 200, result });
103
- });
104
- app.listen(3000, () => {
105
- console.log("✅ Server is running at http://localhost:3000");
106
- });